POI-处理大Excel文件(xls)
最近需要处理一个比较大的excel文件,但是poi在处理文件时会抛出OOM导致程序崩溃,查看官方文档看到可以以流式的方式读取excel避免读取大文件时的OOM。本文主要记述xls的处理。
环境模拟
先准备一个大的excel文件(xls大小8M),再将jvm的heap缩小到100m(JVM 参数 -Xmx100m)用于模拟OOM
并使用参数在OOM时dump内存 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=d://dump.hprof
使用HSSF读取
public static void main(String [] args) throws IOException {
InputStream is = new FileInputStream("d://large.xls");
Workbook wb = new HSSFWorkbook(is);
}
运行之后
Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
at java.lang.Integer.valueOf(Integer.java:832)
at org.apache.poi.hssf.usermodel.HSSFSheet.getRow(HSSFSheet.java:385)
at org.apache.poi.hssf.usermodel.HSSFSheet.setPropertiesFromSheet(HSSFSheet.java:212)
at org.apache.poi.hssf.usermodel.HSSFSheet.<init>(HSSFSheet.java:145)
at org.apache.poi.hssf.usermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:353)
at org.apache.poi.hssf.usermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:398)
at org.apache.poi.hssf.usermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:379)
at blog.excel.EventExample.main(EventExample.java:109)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
就报出OOM,虽然文件只有8M并且heap有100m但是还是发生了OOM,使用jvisualvm查看dump的内容

可以看到创建了许多poi内部的Record(由于我excel内都是数字所以都是NumberRecord)。
使用SAX流式读取
POI提供了SAX流式读取的方式,可以减小内存的使用
//需要继承HSSFListener
public class EventExample implements HSSFListener
{
private SSTRecord sstrec;
/**
* 实现接口方法用于处理每一条记录,包括workbook/row/cell
*/
@Override
public void processRecord(Record record)
{
switch (record.getSid())
{
// 标记workbook或sheet开始,这里会进行判断
case BOFRecord.sid:
BOFRecord bof = (BOFRecord) record;
if (bof.getType() == bof.TYPE_WORKBOOK)
{
System.out.println("Encountered workbook");
// assigned to the class level member
} else if (bof.getType() == bof.TYPE_WORKSHEET)
{
System.out.println("Encountered sheet reference");
}
break;
//处理sheet
case BoundSheetRecord.sid:
BoundSheetRecord bsr = (BoundSheetRecord) record;
System.out.println("New sheet named: " + bsr.getSheetname());
break;
//处理行
case RowRecord.sid:
RowRecord rowrec = (RowRecord) record;
System.out.println("Row found, first column at "
+ rowrec.getFirstCol() + " last column at " + rowrec.getLastCol());
break;
//处理数字单元格
case NumberRecord.sid:
NumberRecord numrec = (NumberRecord) record;
System.out.println("Cell found with value " + numrec.getValue()
+ " at row " + numrec.getRow() + " and column " + numrec.getColumn());
break;
// 包含一行中所有文本单元格
case SSTRecord.sid:
sstrec = (SSTRecord) record;
for (int k = 0; k < sstrec.getNumUniqueStrings(); k++)
{
System.out.println("String table value " + k + " = " + sstrec.getString(k));
}
break;
//处理文本单元格
case LabelSSTRecord.sid:
LabelSSTRecord lrec = (LabelSSTRecord) record;
System.out.println("String cell found with value "
+ sstrec.getString(lrec.getSSTIndex()));
break;
}
}
public static void main(String[] args) throws IOException
{
// 文件inputStream
FileInputStream is = new FileInputStream("d://large.xls");
POIFSFileSystem poifs = new POIFSFileSystem(is);
InputStream din = poifs.createDocumentInputStream("Workbook");
HSSFRequest req = new HSSFRequest();
// 为HSSFRequest增加listener
req.addListenerForAllRecords(new EventExample());
HSSFEventFactory factory = new HSSFEventFactory();
// 处理inputstream
factory.processEvents(req, din);
// 关闭inputstream
is.close();
din.close();
System.out.println("done.");
}
}
不足
使用以上的方法可以读取大文件,而不用担心oom发生。但是只能读到其单元格字面值,HSSF中的样式等都无法获取,而且只能进行读取无法修改、添加,这大大限制了其使用的范围。如果需要进行大文件的追加就需要后面介绍的SXSSF进行处理了。
POI-处理大Excel文件(xls)的更多相关文章
- POI读取/写入Excel文件
import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io ...
- Apache POI 实现对 Excel 文件读写
1. Apache POI 简介 Apache POI是Apache软件基金会的开放源码函式库. 提供API给Java应用程序对Microsoft Office格式档案读和写的功能. 老外起名字总是很 ...
- java中使用poi导入导出excel文件_并自定义日期格式
Apache POI项目的使命是创造和保持java API操纵各种文件格式基于Office Open XML标准(OOXML)和微软的OLE复合文档格式(OLE2)2.总之,你可以读写Excel文件使 ...
- 使用(POI)SAX处理Excel文件,防止内存溢出
POISAXReader h2:first-child, body>h1:first-child, body>h1:first-child+h2, body>h3:first-chi ...
- java读取excel文件(.xls,xlsx,csv)
前提,maven工程通过poi读写excel文件,需要在pom.xml中配置依赖关系: 在<dependencies>中添加如下代码 <dependency> <grou ...
- Java入门开发POI读取导入Excel文件
Apache POI是Apache开发的开源的跨平台的 Java API,提供API给Java程序对Microsoft Office格式档案进行各种操作. POI中Excel操作很简单,主要类有 HS ...
- C# 操作 Excel 文件(.xls 或 .xlsx)
在.net中,常用的操作excel文件的方式,有三种: OLE DB的形式, 第三方框架NPOI, Office组件. 总结: 通过对比,在读取大数据量的excel文件,建议用OLE DB的形式,把e ...
- 关于NPOI导出excel文件(xls和xlsx两种格式)提示格式不符的问题
这两天在做导出excel文件的时候遇到这个问题 本来我导出的格式是xlsx格式的,但是下载得到的文件格式变成了xls, 一开始以为是返回的contenttype设置错了 return File(ms, ...
- 使用poi实现生成excel文件
import java.util.ArrayList; import javax.servlet.ServletOutputStream; import org.apache.poi.hssf.use ...
随机推荐
- Jedis使用示例
http://javacrazyer.iteye.com/blog/1840161 http://www.cnblogs.com/edisonfeng/p/3571870.html
- protobuf python api
摘要: python中一切都可以看作类.那么如何查看每个类的API.使用ipython python protobuf 的函数在message中定义 此处所有的api说明:https://devel ...
- 转 [ javascript面向对象技术
以下文章来自iteye,作者是 sdcyst ,个人主页 http://www.iteye.com/topic/288813 类变量/类方法/实例变量/实例方法先补充一下以前写过的方法:在javasc ...
- 17.4.3 使用MulticastSocket实现多点广播(2)
// 让该类实现Runnable接口,该类的实例可作为线程的target public class MulticastSocketTest implements Runnable { // 使用常量作 ...
- linux下文件和目录的颜色表示
蓝色表示目录: 绿色表示可执行文件: 红色表示压缩文件: 浅蓝色表示链接文件: 灰色表示其它文件: 红色闪烁表示链接的文件有问题了: 黄色是设备文件,包括block, char, fifo. (摘自: ...
- (中等) POJ 1703 Find them, Catch them,带权并查集。
Description The police office in Tadu City decides to say ends to the chaos, as launch actions to ro ...
- margin负值布局(一)
搜索关键词:margin 负-100% 链接地址: 负margin用法权威指南 负边距(negative margin)实现自适应的div左右排版 <div class="cont& ...
- LPC1768IAP(详解,有上位机)
之前说了stm32的iap编程,今天天气真好,顺手就来说说lpc1788的iap编程(没看前面的请查看stm笔记下的内容) 首先是flash的算法,lpc1768并没有寄存器来让我们操作flash,他 ...
- mysql查看sql语句执行时间
原文地址: http://www.cnblogs.com/happySmily/p/5943311.html
- Hibernate 继承表结构
有Product , Book ,Clothes三张表 Product:id,name Book: id ,name,pageCount Clothes: id ,name ,size 创建三张表 产 ...