我想读取一个大的excel文件(.xlsx / .xls)。当我上传20MB的文件时,Java-Heap突然增加了2GB,并遇到OutOfMemoryError。
private Sheet getSheetForFileType(String filType, InputStream fileData) throws IOException {
Workbook workbook;
Sheet sheet;
if (filType.equalsIgnoreCase("xls")) {
workbook = new HSSFWorkbook(fileData); //OutOfMemoryError
sheet = workbook.getSheetAt(0);
} else {
workbook = new XSSFWorkbook(fileData); //OutOfMemoryError
sheet = workbook.getSheetAt(0);
}
return sheet;
}
如此处Apache-POI overview所述,我尝试使用XSSF和SAX(事件API)修改后的代码如下:
private Sheet getSheetForFileType(String filType, InputStream fileData) throws IOException {
if (filType.equalsIgnoreCase("xls")) {
....
} else {
OPCPackage opcPackage = OPCPackage.open(fileData); //OutOfMemoryError
XSSFReader xssfReader = new XSSFReader(opcPackage);
SharedStringsTable sharedStringsTable = xssfReader.getSharedStringsTable();
XMLReader parser = getSheetParser(sharedStringsTable);
....
....
}
return sheet;
}
但是,我无法加载文件并读取它。
我从Input-Stream读取文件数据,目的是ONLY到Read-Data,对此没有写操作。
读取文件占用的内存更少,而InputStream需要更多的内存,因为它必须缓冲整个文件。
我看过其他帖子,据我了解:
Update-1:添加了示例Excel图片。
尝试使用非常高效和高性能的流式SXSSFWorkbook类而不是XSSFWorkbook(它将整个Excel工作簿保留在内存中),如下所示:
SXSSFWorkbook workbook = new SXSSFWorkbook(100);
其中100是将保留在内存中并实时处理的默认行数。