Excel作为一种常用的数据存储格式,在很多项目中都会有相应的导入导出的功能。这篇文章会介绍如何使用Java操作Excel,以及如何解决大文件读写时内存溢出的问题。
1、OpenXML标准
Word、Excel、PPT是Office办公套件中最常用的三个组件。早期的Office套件使用二进制格式,这里面包括以.doc
、.xls
、.ppt
为后缀的文件;直到07这个划时代的版本将基于XML的压缩格式作为默认文件格式,也就是相应以.docx
、.xlsx
、.pptx
为后缀的文件。
这个结合了XML与Zip压缩技术的新文件格式使用的是OpenXML标准。微软从2000年开始酝酿这项技术标准,到2006年申请成为ECMA-376,然后在Office2007中用作默认的文件格式,再到08年成为了ISO / IEC 29500国际标准,后续每两三年就会发布一个新版本。Office的一路凯歌无不彰显微软雄厚的实力。
所以说三流公司做产品,二流公司做平台,一流公司定标准。
微软的官方文档中详细介绍了WordprocessingML(Word)、SpreadsheetML(Excel)、PresentationML(PPT)三个标准,这里主要介绍Excel的部分内容。
首先Excel几个最基础的概念:
- 一个Excel就是一个工作簿(Workbook)
- 一个Sheet就是一张表格
- 一个Workbook可以包含多个Sheet
- 每一行Row的每一列就是一个单元格(Cell)
因为07版后的.xlsx
本质上就是一个压缩包,我们完全可以用解压工具打开它。
一个基础的Excel解压之后,目录结构大致如下:
更典型的Excel还包括:数字、文本、公式、图表(Chart)、普通列表(Table)、数据透视表(Pivot Table)等内容。
Excel远比我们想象的复杂
2、使用POI操作Excel
Java领域最常见的两个操作Excel的工具库分别是JXL(Java Excel API)和Apache的POI。JXL有个严重的缺点就是只支持07版本之前的二进制格式Excel,而POI除了能操作Excel,还可以操作Word和PPT以及Office套装中其他的组件,高下立现。
POI全称是Poor Obfuscation Implementation,简洁模糊实现,也有人翻译成糟糕的模糊实现。
POI目前最新版本是4.0,可以将相应maven依赖添加到pom.xml文件中:
<!-- poi:07版之前的二进制格式 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.0.0</version>
</dependency>
<!-- poi-ooxml:07版之后的OpenXML格式 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.0.0</version>
</dependency>
1、HSSF支持.xls
为后缀的二进制格式,并提供了流解析模式的HSSFListener
相关API以及基于内存模型的HSSFWorkbook
相关API。
2、XSSF支持.xlsx
为后缀的OpenXML格式。因为是底层文件是XML所以可以使用SAX解析,POI提供了XSSFReader
用来获取压缩包中的各个XML文件相应的输入流;另外提供了基于DOM解析模式的XSSFWorkbook
相关API。
3、POI3.8后提供了SXSSF API,它是基于XSSF构建的低内存占用版本(使用滑动窗口机制来实现低内存访问)。但是需要注意的是SXSSFWorkbook默认使用内联字符串而不是共享字符串表(SharedStringsTable),这样可以让保存在内存中的数据尽可能更少(SharedStringsTable需要常驻内存),所以如果是自己写SAX解析要注意兼容性。
POI滑动窗口只窗口范围内的单元格数据加载到内存中,窗口外的数据读写内容会以临时文件的形式保存到磁盘上,同时还支持临时文件的压缩。SXSSF可以通过构造函数中的
rowAccessWindowSize
参数指定窗口大小,compressTmpFiles
指定是否压缩临时文件,useSharedStringsTable
指定是否使用共享字符表。
2.1、使用Workbook API
上面说的三种方式都有一个Workbook实现类,用法上基本一致。唯一不同的是SXSSFWorkbook最后需要调用dispose()
方法处理磁盘上的临时文件。