工作当中遇到要读取大数据量Excel(10万行以上,Excel 2007),用POI方式读取,用HSSFWorkbook读取时,超过2万行JVM的内存就会溢出,在网上找到原来要用XML方式逐行读取,记录下来,以供参考。
注意:运行环境是jdk1.6,如果要在1.5的环境中运行,要把jdk1.6中的rt.jar中javax.xml包下所有类加到运行的环境中。
下面是代码:
package com.bill.excel;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;
public class ExcelUtil extends DefaultHandler {
private SharedStringsTable sst;
private String lastContents;
private boolean nextIsString;
private int sheetIndex = -1;
private List<String> rowlist = new ArrayList<String>();
private int curRow = 0;
private int curCol = 0;
/**
* 读取第一个工作簿的入口方法
* @param path
*/
public void readOneSheet(String path) throws Exception {
OPCPackage pkg = OPCPackage.open(path);
XSSFReader r = new XSSFReader(pkg);
SharedStringsTable sst = r.getSharedStringsTable();
XMLReader parser = fetchSheetParser(sst);
InputStream sheet = r.getSheet("rId1");
InputSource sheetSource = new InputSource(sheet);
parser.parse(sheetSource);
sheet.close();
}
/**
* 读取所有工作簿的入口方法
* @param path
* @throws Exception
*/
public void process(String path) throws Exception {
OPCPackage pkg = OPCPackage.open(path);
XSSFReader r = new XSSFReader(pkg);
SharedStringsTable sst = r.getSharedStringsTable();
XMLReader parser = fetchSheetParser(sst);
Iterator<InputStream> sheets = r.getSheetsData();
while (sheets.hasNext()) {
curRow = 0;
sheetIndex++;
InputStream sheet = sheets.next();
InputSource sheetSource = new InputSource(sheet);
parser.parse(sheetSource);
sheet.close();
}
}
/**
* 该方法自动被调用,每读一行调用一次,在方法中写自己的业务逻辑即可
* @param sheetIndex 工作簿序号
* @param curRow 处理到第几行
* @param rowList 当前数据行的数据集合
*/
public void optRow(int sheetIndex, int curRow, List<String> rowList) {
String temp = "";
for(String str : rowList) {
temp += str + "_";
}
System.out.println(temp);
}
public XMLReader fetchSheetParser(SharedStringsTable sst) throws SAXException {
XMLReader parser = XMLReaderFactory
.createXMLReader("org.apache.xerces.parsers.SAXParser");
this.sst = sst;
parser.setContentHandler(this);
return parser;
}
public void startElement(String uri, String localName, String name,
Attributes attributes) throws SAXException {
// c => 单元格
if (name.equals("c")) {
// 如果下一个元素是 SST 的索引,则将nextIsString标记为true
String cellType = attributes.getValue("t");
if (cellType != null && cellType.equals("s")) {
nextIsString = true;
} else {
nextIsString = false;
}
}
// 置空
lastContents = "";
}
public void endElement(String uri, String localName, String name)
throws SAXException {
// 根据SST的索引值的到单元格的真正要存储的字符串
// 这时characters()方法可能会被调用多次
if (nextIsString) {
try {
int idx = Integer.parseInt(lastContents);
lastContents = new XSSFRichTextString(sst.getEntryAt(idx))
.toString();
} catch (Exception e) {
}
}
// v => 单元格的值,如果单元格是字符串则v标签的值为该字符串在SST中的索引
// 将单元格内容加入rowlist中,在这之前先去掉字符串前后的空白符
if (name.equals("v")) {
String value = lastContents.trim();
value = value.equals("") ? " " : value;
rowlist.add(curCol, value);
curCol++;
} else {
// 如果标签名称为 row ,这说明已到行尾,调用 optRows() 方法
if (name.equals("row")) {
optRow(sheetIndex, curRow, rowlist);
rowlist.clear();
curRow++;
curCol = 0;
}
}
}
public void characters(char[] ch, int start, int length)
throws SAXException {
// 得到单元格内容的值
lastContents += new String(ch, start, length);
}
}
分享到:
相关推荐
在Java开发中,Apache POI库是一个非常实用的工具,用于读取...总之,Apache POI结合SAX API为在Android上处理大数据量Excel文件提供了有效方案,通过合理配置和优化,可以显著降低内存消耗,提高应用的稳定性和效率。
Java中的Apache POI库是用于读取和...通过以上策略,可以有效地处理Java POI在导入大数据量Excel时的内存溢出问题,同时提高程序的运行效率。在实践中,应根据具体场景选择合适的优化方法,确保程序的稳定性和性能。
在处理大数据量的Excel文件时,Java是一种常用的语言,因为它提供了强大的库,如Apache POI,使得解析大型Excel文件成为可能。Apache POI是Java的一个开源项目,专门用于读写Microsoft Office格式的文件,包括Excel...
EasyExcel是阿里巴巴开源的一个轻量级Java库,专门针对大数据量的Excel读写进行了优化。EasyExcel通过事件驱动的模型,只在内存中保留当前处理的行数据,极大地降低了内存消耗。从描述来看,EasyExcel的读取速度比...
本教程将重点讲解如何使用Apache POI库来读取Excel数据,并基于这些数据批量生成Word文档。Apache POI是一个开源项目,它允许Java开发者处理Microsoft Office格式的文件,如Excel(.xlsx或.xls)和Word(.docx)。 ...
然而,当处理的Excel文件特别是XLSL格式的文件数据量巨大时,传统的API,如Apache POI或者JExcelAPI,可能会遇到性能问题,因为它们会一次性加载整个工作簿到内存中,可能导致内存溢出。为了解决这个问题,我们需要...
本案例采用的poi读取大数据的excel文件 usermodel模式对excel操作前需要将文件全部转入内存,对较大文件来说内存开销很大。但是其使用简单。 eventusermodel模式采用事件模型,对文件边读取边处理,内存消耗较低,...
poi读取大量数据会造成gc内存溢出的报错,由于垃圾回收机制无法将大量的对象及时的回收,而这些对象又会保存在内存中,会导致内存不够用的情况,这时候我们就需要使用新的方法,读取为cvs即可.此解决方案可支持千万数据的...
POI百万级大数据量EXCEL导出 - 请叫我猿叔叔的博客 - CSDN博客.htm
Java 使用 Apache POI 读取 Excel 是一个常见的任务,在处理数据导入、导出或数据分析时非常有用。Apache POI 是一个流行的开源库,它允许 Java 开发者创建、修改和显示 Microsoft Office 格式的文件,其中包括 ...
在Java中,读取和操作Excel文件是常见的需求,这通常涉及到使用库,如Apache POI和JXL。这两个库都允许开发者在Java中方便地读取、写入和修改Excel文件。 Apache POI是一个强大的库,专门用于处理Microsoft Office...
本资源“使用Poi读取大数据量excel的方法”提供了处理大量数据时使用POI进行有效读取的示例代码。以下是关于如何使用POI高效地处理大数据量Excel文件的一些关键知识点: 1. **POI组件**: - HSSF:处理Excel 97-...
该压缩包里面有两个文件,TestExcel.java主要是原始的处理方法,操作简单,适合小数据量的读取。 ExampleEventUserModelUtil.java是处理大数据量的。users40.xlsx是测试文件,里面有40万条数据。 jar包都在jar文件夹...
通过以上步骤,我们可以在Java中使用Apache POI实现大数据量的Excel导出。实际开发中,可能还需要考虑如数据分页、数据过滤、多线程处理等高级功能,以进一步提高性能和用户体验。记得在使用完毕后释放资源,如关闭...
总结来说,解决Java读取Excel内存溢出问题,关键在于合理利用资源、优化代码逻辑以及选择适合的API,如Apache POI的SXSSF。通过这些方法,我们可以在不显著增加系统资源负担的情况下,高效地处理大Excel文件。
在这个5.2.1版本中,POI提供了对Excel电子表格的强大支持,包括读取数据、修改内容、创建新工作簿以及处理复杂的公式和样式。 `poi-ooxml-lite-5.2.1.jar`:这个轻量级的JAR文件包含了处理OOXML(Office Open XML)...
这样,对于不同结构的Excel文件,只需要改变输入的Bean类,就能轻松读取数据。 兼容03/07版Excel的功能意味着ExcelUtil支持两种主要的Excel文件格式:.xls(97-2003版本)和.xlsx(2007及以上版本)。这得益于...
综上所述,Java读取大型Excel文件涉及的关键点在于选择合适的API,采用分块读取、迭代器、错误处理、性能优化和可能的数据库集成。理解并应用这些技术将帮助你在处理大数据量的Excel文件时更加得心应手。
在java web系统应用中我们经常会用到大批量数据的导出,动辄就上几十万几百万的数据让我们的程序感觉...java中使用poi导出Excel大批量数据到客户端 存在两个导出方法:存在一个分批量导出ZIP文件,一个导出exel文件