我正在使用XSSF
apache-POI
来读取XLSX文件。我收到了错误java.lang.OutOfMemoryError: Java heap space
。稍后,使用-Xmx1024m
为java类增加堆大小仍然会重复相同的错误。
代码:
String filename = "D:\\filename.xlsx";
FileInputStream fis = null;
try {
fis = new FileInputStream(filename);
XSSFWorkbook workbook = new XSSFWorkbook(fis);
在上面的代码段中,执行在XSSFWorkbook
处停止并抛出指定的错误。
有人可以建议更好的方法来读取大型XLSX文件。
答案 0 :(得分:15)
POI允许您以流方式读取Excel文件。 API几乎是SAX的包装器。确保使用带有String的构造函数以正确的方式打开OPC包。否则你可能会立即耗尽内存。
OPCPackage pkg = OPCPackage.open(file.getPath());
XSSFReader reader = new XSSFReader(pkg);
现在,读者将允许您获取不同部分的InputStreams
。如果您想自己进行XML解析(使用SAX或StAX),可以使用它们。但它需要非常熟悉格式。
更简单的选择是使用XSSFSheetXMLHandler。以下是读取第一张表的示例:
StylesTable styles = reader.getStylesTable();
ReadOnlySharedStringsTable sharedStrings = new ReadOnlySharedStringsTable(pkg);
ContentHandler handler = new XSSFSheetXMLHandler(styles, sharedStrings, mySheetContentsHandler, true);
XMLReader parser = XMLReaderFactory.createXMLReader();
parser.setContentHandler(handler);
parser.parse(new InputSource(reader.getSheetsData().next()));
mySheetsContentHandler应该是您自己的XSSFSheetXMLHandler.SheetContentsHandler实现。这个类将被输入行和单元格。
但请注意,如果您的共享字符串表很大(如果您的巨大工作表中没有任何重复的字符串,则会发生这种情况,这可能会适度占用内存)。如果内存仍然存在问题,我建议使用原始XML流(也由XSSFReader提供)。
答案 1 :(得分:0)
为了补充@waxwing 的回答,如果输入的 XLS(X) 文件受密码保护,您将需要通过用解密装饰器包装原始文件来获取纯输入流。但首先,您需要将文件作为 POIFSFileSystem
打开。
简而言之:
String pass = "secret";
File file = new File("data/1.xlsx");
try (POIFSFileSystem fs = new POIFSFileSystem(file);
// wrap in org.apache.poi.poifs.filesystem.DocumentFactoryHelper.getDecryptedStream
InputStream in = DocumentFactoryHelper.getDecryptedStream(fs, pass);
OPCPackage pkg = OPCPackage.open(in))
{
XSSFReader reader = new XSSFReader(pkg);
StylesTable styles = reader.getStylesTable();
ReadOnlySharedStringsTable sharedStrings = new ReadOnlySharedStringsTable(pkg);
SheetContentsHandler f = new SheetContentsHandler() {
// ... your implementation of SheetContentsHandler interface ...
};
ContentHandler handler = new XSSFSheetXMLHandler(styles, sharedStrings, f, true);
XMLReader parser = XMLReaderFactory.createXMLReader();
parser.setContentHandler(handler);
parser.parse(new InputSource(reader.getSheetsData().next()));
}