【问题标题】:How to read XLSX file of size >40MB如何读取大小>40MB 的 XLSX 文件
【发布时间】:2012-07-05 13:16:55
【问题描述】:

我正在使用 XSSFapache-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 文件。

【问题讨论】:

  • 你像eclipse一样从IDE运行它吗?你是如何设置内存选项的?我认为您的设置可能没有正确生效。
  • 是的,我正在使用 Eclipse IDE 并对其进行了以下更改...1)在 eclipse.ini 中将 -Xmx256M 编辑为 -Xmx-1024M 2)在 IDE 窗口中->首选项- >已安装 JRE->在默认 VM 参数中添加了 -Xms256M -Xmx1024M。我认为它可能反映在 eclipse IDE 中

标签: java out-of-memory xlsx


【解决方案1】:

POI 允许您以流式方式读取 excel 文件。 API 几乎是 SAX 的包装器。确保使用接受字符串的构造函数以正确的方式打开 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 提供)。

【讨论】:

【解决方案2】:

为了补充@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()));
}

【讨论】:

    猜你喜欢
    • 2023-03-22
    • 2011-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-25
    • 2014-03-03
    • 2017-04-26
    • 2023-03-27
    相关资源
    最近更新 更多