1.前言
相信大家都应该看到过下面的功能:
文件的导入导出:
这个功能主要就是帮助我们的用户能够快速的将数据导入到数据库中,不用在自己手动的一条一条的将数据新增到我们的数据库中.同时又能够方便我们能够将数据导出之后打印出来给领导们查看.不用非得带着电脑这里那里的跑.非常实用的功能.
功能好是好,但是这样的功能我们又应该怎么来开发呢,主要用到的技术又有那些呢?知道该用那些技术之后,我们又应该怎么来使用呢?相信大家肯定都有这样那样的困扰,正是因为大家有这样那样的困扰,所以就更加需要看看这篇文章了.这里我会用案例+代码+源码的方式带大家更好的学习这方面的知识.
文件的导入导出功能目前主要是两家独大,一个就是Apache的POI,另一家就是阿里的EasyExcel.这里两种技术我都会在下面的文章里面详细讲解.
2.POI:
2.1-POI介绍:
POI的全称是: Poor Obfuscation Implementation ,意思是可怜的模糊实现.说是可怜但是一点都不可怜.是由Apache公司用Java开发并且免费开源的一套Java Api.
它能够帮助我们简单快速的对Excel的数据进行读写的操作.他不仅支持Excel,同时也支持PowerPoint,Word等等,但是这两者我们就暂时不讲,我们主要需要了解的就是关于Excel的操作.
POI所需的依赖:
<!-- xls03版本--> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.9</version> </dependency> <!-- xlsx07版本--> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.9</version> </dependency> <!-- 日期格式化工具--> <dependency> <groupId>joda-time</groupId> <artifactId>joda-time</artifactId> <version>2.10.1</version> </dependency> <!-- test--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency>
2.2-03版Excel与07版Excel区别
在使用POI之前,我们需要先了解一下Excel的版本更替,这样能够方便我们更好的了解POI的使用.
这里面Excel主要就是有两类,分别是Excel03版本和Excel07版本
这两个版本之间主要有以下的差别:
两者数据量都是有限制的
03版本行数最多只能到65536,列数最多只能到256
03版本行数最多只能到1048576 ,列数最多只能到16384
03版本:
行数限制:
列数限制:
9*29+22=256(简单的四则运算)
07版本:
行数限制:
列数限制:
两者的文件名后缀也不一样,03版本的后缀是xls,07版本的后缀是xlsx,既然两者的后缀不一样就说明操作两者的工具类肯定也就是不一样的,这一点我们会在下面的代码中着重体现,其次就是 .xlsx文件比.xls的压缩率高,也就是相同数据量下,.xlsx的文件会小很多。
2.3-数据写入操作
知道上述两者的差异之后,才能更好的方便我们下面处理我们编写过程中可能遇到的bug.
其次在java中有一个非常重要的理念就是"万物皆对象",所以我们想要操作Excel表格的话,就要知道表格具体是由那些对象构成的.
具体分下来主要就是图中标注出来的几种对象:工作簿,工作表,行,单元格
了解完有上述对象之后,我们就通过一个简单的案例来帮助大家更好的 了解这个概念.
具体代码实现:
- 03版本-HSSFWorkbook:
@Test public void testExcel03() throws Exception{ //创建一个工作簿 Workbook workbook=new HSSFWorkbook(); //创建一张工作表 Sheet sheet=workbook.createSheet("我是一个新表格"); //创建一行即(1,1)的单元格 Row row1=sheet.createRow(0); Cell cell11=row1.createCell(0); //往该单元格中填充数据 cell11.setCellValue("姓名"); //创建(1,2)单元格 Cell cell12=row1.createCell(1); cell12.setCellValue("印某人"); Row row2=sheet.createRow(1); Cell cell21=row2.createCell(0); cell21.setCellValue("注册日期"); Cell cell22=row2.createCell(1); String time=new DateTime().toString("yyyy-MM-dd HH:mm:ss"); cell22.setCellValue(time); //创建文件流 FileOutputStream fileOutputStream=new FileOutputStream(PATH+"登记表03.xls"); //把文件流写入到工作簿中 workbook.write(fileOutputStream); //关闭文件流 fileOutputStream.close(); System.out.println("文件生成成功"); }
运行完代码之后我们就可以看到我们的文件夹下面就生成了登记表03.xls这样一个文件
打开文件之后我们也能发现,数据的确已经写进来了.
- 07版本-XSSFWorkbook:
@Test public void testExcel07()throws Exception{ //注意只有这里创建的对象是不一样的!!!!! Workbook workbook=new XSSFWorkbook(); Sheet sheet=workbook.createSheet("我是一个新表格"); Row row1=sheet.createRow(0); Cell cell11=row1.createCell(0); cell11.setCellValue("姓名"); Cell cell12=row1.createCell(1); cell12.setCellValue("印某人"); Row row2=sheet.createRow(1); Cell cell21=row2.createCell(0); cell21.setCellValue("注册日期"); Cell cell22=row2.createCell(1); String time=new DateTime().toString("yyyy-MM-dd HH:mm:ss"); cell22.setCellValue(time); FileOutputStream fileOutputStream=new FileOutputStream(PATH+"登记表07.xlsx"); workbook.write(fileOutputStream); fileOutputStream.close(); System.out.println("文件生成成功"); }
可以看到在上面的代码中我们除了修改了创建的对象之外,其他的代码,我们都是没有修改的.本质操作都是一致的.
2.4-HSSFWorkbook,XSSFWorkbook,SXSSFWorkbook大数据量下写入速度对比
我们了解了基本的写入数据的流程之后,接下来我们测试一下,在大数据量的情况下,他们生成相应的文件需要多长的时间,看看他们两者的性能又是如何的.顺便我们也了解一下他们写入数据的整个流程.
03版本-HSSFWorkbook:
@Test public void test03BigData()throws Exception{ Long begin=System.currentTimeMillis(); Workbook workbook=new HSSFWorkbook(); Sheet sheet=workbook.createSheet(); for(int rownum=0;rownum<65536;rownum++){ Row row=sheet.createRow(rownum); for(int cellnum=0;cellnum<10;cellnum++){ Cell cell=row.createCell(cellnum); cell.setCellValue(cellnum); } } FileOutputStream fileOutputStream=new FileOutputStream(PATH+"test03BigData.xls"); workbook.write(fileOutputStream); System.out.println("文件生成完毕"); Long end=System.currentTimeMillis(); System.out.println("共用时:"+(double)(end-begin)/1000+"秒"); }
这里我们运行完成之后可以看到一共运行了1.811秒,还是很快的
但是就上我们上面所说的一样,03版本的只支持最多65536条数据,如果超过这个数据量的话,是会报这个错的: Invalid row number (65536) outside allowable range (0…65535) ,这里我们运行测试一下看一下报错:
看完他的运行速度之后我们来看看,为什么HSSFWorkbook能够这么快就能将数据写入到文件中呢.
因为HSSFworkbook是直接将整个文件写入到内存中的,文件直接就能从内存中读到,所以使得整个写入的过程十分的快速.既然选择写入内存里面,那么就会出现一个问题那就是内存不够,直接就爆了,严重影响性能,所以可能是出于这个问题的考虑,03版本才会限制数据的条数(后面部分是我自己猜的,嘤嘤嘤)
07版本-XSSFWorkbook:
@Test public void test07BigData()throws Exception{ Long begin=System.currentTimeMillis(); Workbook workbook=new XSSFWorkbook(); Sheet sheet=workbook.createSheet(); for(int rownum=0;rownum<65537;rownum++){ Row row=sheet.createRow(rownum); for(int cellnum=0;cellnum<10;cellnum++){ Cell cell=row.createCell(cellnum); cell.setCellValue(cellnum); } } FileOutputStream fileOutputStream=new FileOutputStream(PATH+"test07BigData.xlsx"); workbook.write(fileOutputStream); System.out.println("文件生成完毕"); Long end=System.currentTimeMillis(); System.out.println("共用时:"+(double)(end-begin)/1000+"秒"); }