这里我们再来看一下XSSFWorkbook写入数据的速度:
同样的数据量,用时6.633秒
我们再来看一下如果是10万条数据的话,看看时间会是多少:
用时10.013秒,时间还能接受,毕竟在10万条数据的情况下
既然这样我们也来分析一下XSSFWorkbook写入数据的流程,这里XSSFWorkbook和HSSFWorkbook一样,也是直接将数据写入内存中的,但是我们要知道因为XSSFWorkbook支持的数据量更多了,所以就必定会出现OOM即内存爆掉的情况,所以怎么办呢,这里我猜想的是,他是按照一定的量来将数据写入内存之中,就好比我是每10000条写入内存一次,那样的话,既能较快的写入数据,同时又能够支持比较大的数据量----这里也是我自己的猜想,感觉应该是这样.
大致可以通过下面的图来模拟:
07版本进阶-SXSSFWorkbook
@Test public void test07BigDataS()throws Exception{ Long begin=System.currentTimeMillis(); Workbook workbook=new SXSSFWorkbook(); 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+"test07BigDataS.xlsx"); workbook.write(fileOutputStream); System.out.println("文件生成完毕"); Long end=System.currentTimeMillis(); System.out.println("共用时:"+(double)(end-begin)/1000+"秒"); }
大家看名字就知道这个SXSSFWorkbook其实就是XSSFWorkbook的加强版(Super XSSFWorkbook),他的优点比较明显,既能够支持写入大量的数据,同时写入数据的速度也是非常的快.
这里我们上来就直接测试10万条数据玩玩:
这速度跟闹着玩一样,10万条数据只要1.813秒,属实是牛逼
既然这样我们就更加要深挖一下,这玩意儿为啥这么快呢?
按照网上的说法,其实XSSFWorkbook写入数据的思路和XSSFWorkbook写入数据的思路差不多的,上面我们说过了XSSFWorkbook写入数据是每隔一个数据量进行输入,在已经向内存写入10000条数据后,程序就在进行等待,
等待着10000条数据写入文件之后,他才继续向内存里面写入数据.
SXSSFWorkbook的思路是这样,他一开始也是向内存里面写入数据,但是他有一个临界值默认是100.超过这个数据量之后的数据,他会自动在磁盘上创建一个临时文件,将数据写入该文件中,之后当内存中的数据写完之后就直接从临时文件中将数据拷贝过来,这样就大大的节省了时间,可以看到程序执行过程是没有断开的,是一直在执行的,意味着最耗时的部分一直在工作.所以才会使得SXSSFWorkbook既能写入大量的数据,同时又能够在非常快的时间内完成.
大致可以通过下面的图来模拟:
其次就是SXSSFWorkbook与XSSFWorkbook有本质上的区别,这个我们可以通过他们引入的包名看出来:
可以看到SXSSFWorkbook本质上是通过流来实现的,XSSFWorkbook则还是通过usermodel来实现的.显然流肯定是更快一点的.
并且这个临时文件并不是直接显示在项目路径下的一般都是存储在与该路径类似的路径下:C:\Users\瓤瓤\AppData\Local\Temp
这是我写入数据时生成的临时文件:
文件名一般都是以POI开头
2.5-POI数据读取操作
03版本-HSSFWorkbook:
@Test public void test03Read()throws Exception{ //引入输入文件流 FileInputStream fileInputStream=new FileInputStream(PATH+"test03BigData.xls"); //创建工作簿 Workbook workbook=new HSSFWorkbook(fileInputStream); //通过索引创建工作表 Sheet sheet=workbook.getSheetAt(0); //通过索引获取行 Row row=sheet.getRow(0); //通过索引获取单元格 Cell cell=row.getCell(0); //打印单元格内容 System.out.println(cell.getNumericCellValue()); }
这是最简单的读写操作流程.并且其中的工作表,行,单元格都是通过索引来获取,除了索引,POI还为我们提供了其他的获取方法,下面我们来详细说明一下.
获取工作表:
第一种就是直接通过工作表的表名来进行获取,第二种就是直接通过工作簿内工作表的索引来进行获取.
获取行就是只能通过索引来获取
剩下的就是获取单元格了:
第一种也是直接通过索引来进行获取,第二种只不是多加了一层的判断语句,这个我们可以点进源码里面看一下:
主要有这三个
RETURN_NULL_AND_BLANK
英文解释: Missing cells are returned as null, Blank cells are returned as normal
缺失的单元格会返回为空,空的单元格就正常返回即可。
RETURN_BLANK_AS_NULL
英文解释: Missing cells are returned as null, as are blank cells
缺失的单元格返回为空,空的单元格也是如此。
RETURN_BLANK_AS_NULL
英文解释: A new, blank cell is created for missing cells. Blank cells are returned as normal
缺失的单元格不仅返回为空,同时还将为这个缺失的单元格创建一个新的单元格。空的单元格就正常返回即可。
其实这三种概念的理念差不多,基本上主要都是用来处理如果出现缺失的单元格情况时,可能会影响后续数据的读写操作。
07版本-XSSFWorkbook:
@Test public void test07Read()throws Exception{ FileInputStream fileInputStream=new FileInputStream(PATH+"test07BigData.xlsx"); Workbook workbook=new XSSFWorkbook(fileInputStream); Sheet sheet=workbook.getSheetAt(0); Row row=sheet.getRow(0); Cell cell[]=new Cell[4]; cell[0]=row.getCell(0); cell[1]=row.getCell(1,Row.RETURN_NULL_AND_BLANK); cell[2]=row.getCell(2); cell[3]=row.getCell(3); for(int i=0;i<4;i++){ System.out.println(cell[i]); } }
可以看到我们只是简单的修改了一下对象,其他的操作我们都是没有改的,所以我们在编写的时候,只需要注意我们版本对应的对象就行了.