How to read XLSX file of size >40MB
我正在使用
代码:
1 2 3 4 5 | String filename ="D:\\\\filename.xlsx"; FileInputStream fis = null; try { fis = new FileInputStream(filename); XSSFWorkbook workbook = new XSSFWorkbook(fis); |
在上面的代码段中,执行在
有人可以建议更好的方法来读取大型 XLSX 文件。
POI 允许您以流式方式读取 excel 文件。 API 几乎是 SAX 的package器。确保使用接受字符串的构造函数以正确的方式打开 OPC 包。否则你可能会立即耗尽内存。
1 2 | OPCPackage pkg = OPCPackage.open(file.getPath()); XSSFReader reader = new XSSFReader(pkg); |
现在,阅读器将允许您获取不同部分的
更简单的选择是使用 XSSFSheetXMLHandler。这是读取第一张纸的示例:
1 2 3 4 5 6 7 | 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 提供)。
为了补充@waxwing 的答案,如果输入 XLS(X) 文件受密码保护,您将需要通过使用解密装饰器package原始文件来获取纯输入流。但首先,您需要将文件作为
打开
简而言之:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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())); } |