前言
在我们的项目中,经常会使用项目导入和导出的功能。本文以操作Excel为例,目前比较流行的是Apache POI和阿里巴巴的EasyExcel。
Apache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程序对Microsoft Office格式档案读和写的功能。
Apache POI常用的类
- HSSF - 提供读写Microsoft Excel XLS格式档案的功能。
- XSSF - 提供读写Microsoft Excel OOXML XLSX格式档案的功能。
- HWPF - 提供读写Microsoft Word DOC97格式档案的功能。
- XWPF - 提供读写Microsoft Word DOC2003格式档案的功能。
- HSLF - 提供读写Microsoft PowerPoint格式档案的功能。
- HDGF - 提供读Microsoft Visio格式档案的功能。
- HPBF - 提供读Microsoft Publisher格式档案的功能。
- HSMF - 提供读Microsoft Outlook格式档案的功能。
POI使用
引入依赖
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
</dependency>
HSSF方式
缺点:通过HSSF方式写入大量数据,最多只能处理65536行,超过65536行会报错。
优点:通过HSSF方式写入65536行数据,消耗的时间很短,处理过程全部写入缓存,不操作磁盘,最后一次性写入磁盘,速度很快。
@Test
public void hssfTest() throws IOException {
String PATH = "E:\\code\\javaSE\\";
long start = System.currentTimeMillis();
//创建一个工作簿
Workbook workbook = new HSSFWorkbook();
//创建一个表
Sheet sheet = workbook.createSheet("xls03版本");
for (int rowNum = 0; rowNum < 65537; rowNum++) {
//创建行
Row row = sheet.createRow(rowNum);
for (int cellRow = 0; cellRow < 10; cellRow++) {
//创建列
Cell cell = row.createCell(cellRow);
cell.setCellValue(cellRow);
}
}
System.out.println("over");
//生产一张表(IO流) 03版本的用xls结尾
FileOutputStream fileOutputStream = new FileOutputStream(PATH + "PoiHSSF01.xls");
workbook.write(fileOutputStream);
fileOutputStream.close();
long end = System.currentTimeMillis();
System.out.println((double) (end - start)/1000);
}
报错:java.lang.IllegalArgumentException: Invalid row number (65536) outside allowable range (0..65535)
@Test
public void hssfTest() throws IOException {
String PATH = "E:\\code\\javaSE\\";
long start = System.currentTimeMillis();
//创建一个工作簿
Workbook workbook = new HSSFWorkbook();
//创建一个表
Sheet sheet = workbook.createSheet("03xls");
for (int rowNum = 0; rowNum < 65536; rowNum++) {
//创建行
Row row = sheet.createRow(rowNum);
for (int cellRow = 0; cellRow < 10; cellRow++) {
//创建列
Cell cell = row.createCell(cellRow);
cell.setCellValue(cellRow);
}
}
System.out.println("over");
//生产一张表(IO流) 03版本的用xls结尾
FileOutputStream fileOutputStream = new FileOutputStream(PATH + "PoiHSSF01.xls");
workbook.write(fileOutputStream);
fileOutputStream.close();
long end = System.currentTimeMillis();
System.out.println((double) (end - start)/1000);
}
over
2.163
XSSF方式
优点:可以写入大量数据,如20万条
缺点:写数据速度很慢,非常耗内存,也会发生内存溢出,如:写入100万条数据时
@Test
public void xssfTest() throws IOException {
String PATH = "E:\\code\\javaSE\\";
long start = System.currentTimeMillis();
//创建一个工作簿
Workbook workbook = new XSSFWorkbook();
//创建一个表
Sheet sheet = workbook.createSheet("07xlsx");
for (int rowNum = 0; rowNum < 200000; rowNum++) {
//创建行
Row row = sheet.createRow(rowNum);
for (int cellRow = 0; cellRow < 10; cellRow++) {
//创建列
Cell cell = row.createCell(cellRow);
cell.setCellValue(cellRow);
}
}
System.out.println("over");
//生产一张表(IO流) 03版本的用xlsx结尾
FileOutputStream fileOutputStream = new FileOutputStream(PATH + "PoiHSSF01.xlsx");
workbook.write(fileOutputStream);
fileOutputStream.close();
long end = System.currentTimeMillis();
System.out.println((double) (end - start)/1000);
}
over
22.504
SXSSF方式
优点:可以写入非常大量数据时,速度很快,占用内存少
注意:过程中会产生临时文件,需要清理临时文件
@Test
public void sxssfTest() throws IOException {
String PATH = "E:\\code\\javaSE\\";
long start = System.currentTimeMillis();
//创建一个工作簿
Workbook workbook = new SXSSFWorkbook();
//创建一个表
Sheet sheet = workbook.createSheet("07sxlsx");
for (int rowNum = 0; rowNum < 200000; rowNum++) {
//创建行
Row row = sheet.createRow(rowNum);
for (int cellRow = 0; cellRow < 10; cellRow++) {
//创建列
Cell cell = row.createCell(cellRow);
cell.setCellValue(cellRow);
}
}
System.out.println("over");
//生产一张表(IO流) 07版本的用xlsx结尾
FileOutputStream fileOutputStream = new FileOutputStream(PATH + "PoiHSSF02.xlsx");
workbook.write(fileOutputStream);
fileOutputStream.close();
//清除临时文件
((SXSSFWorkbook) workbook).dispose();
long end = System.currentTimeMillis();
System.out.println((double) (end - start)/1000);
}
over
3.867
小结
-
使用xls后缀(HSSFWorkbook)的文件写入会非常快,但是存储数量有限(写入缓存,不操作磁盘,最后一次写入磁盘)。
-
使用xlsx后缀(XSSFWorkbook)的文件写入不快,但是理论上能无限存。
-
希望又能写入大量数据,又快,那就需要使用 SXSSFWorkbook 对象。