JAVA笔记-如何将百万级数据高效的导出到Excel表单

         

 

  今天,一朋友问我使用JAVA有没有什么办法导出百万级的数据到Excel工做表。html

  当时个人第一个念头就是这真的是一个好疯狂的念头。而后就想假如真的有这样相似的需求,我本身应该怎么作呢?java

  

  ps: 首先科普一下基础知识apache

  Excel 2003及如下的版本。一张表最大支持65536数据,256列。也就是说excel2003彻底不可能知足百万数据导出的需求。app

  Excel 2007-2010版本。一张表最大支持1048576行,16384列;dom

  笔者使用的是office 2010,更高的版本笔者没有使用过,暂时没法判断。socket

  由此看来百万级的数据量对Excel自身已是属于接近极限的程度。xss

  假如咱们有更大的需求怎么办呢?maven

  既然单表支持最大是104w条数据,那么更大的需求量咱们就只能经过程序级分表操做的方式来实现了。O(∩_∩)O哈哈~编辑器

 

  对于操做Excel的类库。笔者其实了解的并非不少。只是很早之前使用过POI这个类库,感受很不错。因而决定从它入手。看看POI有没有什么比较有效的好点的解决办法。因为笔者之前使用的POI版本比较低。并且使用于excel 2003版本。因此遇到了很多问题。学习

  

  编辑器: Intellij IDEA 13.2

  类库需求: POI-3.10-Final

1 <dependency>
2             <groupId>org.apache.poi</groupId>
3             <artifactId>poi</artifactId>
4             <version>3.10-FINAL</version>
5         </dependency>

 

  新建一个Maven项目。

  根据笔者以往的经验,直接使用POI写了一份代码。执行的时候直接报错了。

 1 public static void Excel2003Operate(String filePath) throws Exception {
 2         HSSFWorkbook hssfWorkbook = new HSSFWorkbook(new FileInputStream(new File(filePath)));
 3         HSSFSheet sheet = hssfWorkbook.getSheetAt(0);
 4         for (int i = 0; i < 10000; i++) {
 5             HSSFRow hssfRow = sheet.createRow(i);
 6             for (int j = 0; j < 10; j++) {
 7                 HSSFCellUtil.createCell(hssfRow, j, String.valueOf(Math.random()));
 8             }
 9         }
10         FileOutputStream out = new FileOutputStream("workbook.xlsx");
11         hssfWorkbook.write(out);
12         out.close();
13     }
 1 Connected to the target VM, address: '127.0.0.1:62382', transport: 'socket'
 2 Exception in thread "main" org.apache.poi.poifs.filesystem.OfficeXmlFileException: The supplied data appears to be in the Office 2007+ XML. You are calling the part of POI that deals with OLE2 Office Documents. You need to call a different part of POI to process this data (eg XSSF instead of HSSF)
 3     at org.apache.poi.poifs.storage.HeaderBlock.<init>(HeaderBlock.java:131)
 4     at org.apache.poi.poifs.storage.HeaderBlock.<init>(HeaderBlock.java:104)
 5     at org.apache.poi.poifs.filesystem.POIFSFileSystem.<init>(POIFSFileSystem.java:128)
 6     at org.apache.poi.hssf.usermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:342)
 7     at org.apache.poi.hssf.usermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:323)
 8     at dev.tinyz.excel.POIUtil.Excel2003Operate(POIUtil.java:23)
 9     at dev.tinyz.excel.Main.main(Main.java:16)
10 Disconnected from the target VM, address: '127.0.0.1:62382', transport: 'socket'

  运行直接报错了。仔细看了报错信息以后发现。POI要操做excel 2007及以上的版本须要使用XSSF来代替上面代码的HSSF。

  

  发现类库竟然没有XSSF相关的类。着笔者傻眼了说。因而去POI官网查看。发现完整的POI类库包含的内容不少。因而详细了解了一下每一个部分的具体做用:

  poi-ooxml和poi-ooxml-schemas是poi对2007及以上版本的扩充。因而在maven依赖中增长:

 1 <dependency>
 2             <groupId>org.apache.poi</groupId>
 3             <artifactId>poi-ooxml</artifactId>
 4             <version>3.10-FINAL</version>
 5         </dependency>
 6         <dependency>
 7             <groupId>org.apache.poi</groupId>
 8             <artifactId>poi-ooxml-schemas</artifactId>
 9             <version>3.10-FINAL</version>
10         </dependency>

  赶忙修改本身的代码。实现了支持Excel 2010版本。瞬间有种大功告成的感受,有木有。。O(∩_∩)O哈哈~。好有成就感的说。

 1 public static void Excel2007AboveOperateOld(String filePath) throws IOException {
 2         XSSFWorkbook workbook = new XSSFWorkbook(new FileInputStream(new File(filePath)));
 3         // 获取第一个表单
 4         Sheet first = workbook.getSheetAt(0);
 5         for (int i = 0; i < 100000; i++) {
 6             Row row = first.createRow(i);
 7             for (int j = 0; j < 11; j++) {
 8                 if(i == 0) {
 9                     // 首行
10                     row.createCell(j).setCellValue("column" + j);
11                 } else {
12                     // 数据
13                     if (j == 0) {
14                         CellUtil.createCell(row, j, String.valueOf(i));
15                     } else
16                         CellUtil.createCell(row, j, String.valueOf(Math.random()));
17                 }
18             }
19         }
20         // 写入文件
21         FileOutputStream out = new FileOutputStream("workbook.xlsx");
22         workbook.write(out);
23         out.close();
24     }

  赶忙运行跑起来。第一次测试写入1w条数据。耗时8秒多点。感受写入速度好慢,1w条8秒,100w。。个人天。这效率彻底不能接受。因而测试10w,看看测试一下是否是真的写入速度过慢。测试结果让人崩溃。

1 Cast time : 49699

  测试导出10w条数据到excel耗时将近50秒。因而这种方式被暂时放弃。成就感瞬间被打落在地。

  

  再次回到POI的官网。http://poi.apache.org/spreadsheet/index.html

  官方提到自POI3.8版本开始提供了一种SXSSF的方式,用于超大数据量的操做。因而...

  原文:

  SXSSF is an API-compatible streaming extension of XSSF to be used when very large spreadsheets have to be produced...

  

    立刻开动修改代码。代码以下:

 1 public static void Excel2007AboveOperate(String filePath) throws IOException {
 2         XSSFWorkbook workbook1 = new XSSFWorkbook(new FileInputStream(new File(filePath)));
 3         SXSSFWorkbook sxssfWorkbook = new SXSSFWorkbook(workbook1, 100);
 4 //            Workbook workbook = WorkbookFactory.create(new FileInputStream(new File(filePath)));
 5         Sheet first = sxssfWorkbook.getSheetAt(0);
 6         for (int i = 0; i < 100000; i++) {
 7             Row row = first.createRow(i);
 8             for (int j = 0; j < 11; j++) {
 9                 if(i == 0) {
10                     // 首行
11                     row.createCell(j).setCellValue("column" + j);
12                 } else {
13                     // 数据
14                     if (j == 0) {
15                         CellUtil.createCell(row, j, String.valueOf(i));
16                     } else
17                         CellUtil.createCell(row, j, String.valueOf(Math.random()));
18                 }
19             }
20         }
21         FileOutputStream out = new FileOutputStream("workbook.xlsx");
22         sxssfWorkbook.write(out);
23         out.close();
24     }

  屡次运行测试。查看数据

1 Cast time : 11604

  看到数据的瞬间感受,哇塞。好给力的说。竟然从将近50秒缩短带11秒。。。

  为何都是代码差距就这么大呢?

  原来,SXSSF实现了一套自动刷入数据的机制。当数据数量达到必定程度时(用户能够本身设置这个限制)。像文本中刷入部分数据。这样就缓解了程序运行时候的压力。达到高效的目的。O(∩_∩)O哈哈~

 

  再一次测试单表写入100w条数据。

1 Cast time : 87782

  将近90秒就完成了100w条数据的写入。O(∩_∩)O哈哈~。   虽然看上去依旧有一点慢。可是考虑到数据量这样的耗时,想来已是能够接受的了。100w条数据生成的Excel表单竟然有136mb。打开就这个文档都花了很多时间。哈哈

  晒一下成就:

  

  

  源码下载:http://pan.baidu.com/s/1bnw9pYB

  笔者能力有限。暂时只是使用POI类库实现了相对高效的批量写入。假若有更好的类库或者是方法的朋友。欢迎留言分享。多谢指点。。O(∩_∩)O哈哈~   

 

做者:TinyZ
出处:http://www.cnblogs.com/zou90512/
关于做者:努力学习,每天向上。不断探索学习,提高自身价值。记录经验分享。
本文版权归做者和博客园共有,欢迎转载,但未经做者赞成必须保留此段声明,且在文章页面明显位置给出原文连接
若有问题,能够经过 zou90512@126.com 联系我,很是感谢。
笔者网店: shop70768633.taobao.com. 欢迎广大读者围观

相关文章
相关标签/搜索