我在使用Apache POI处理.xlsx文件时遇到问题。我已阅读了StackOverflow上的许多线程,以及Intellij和Oracle网站上的支持,并尝试实施推荐的修补程序。每当JVM尝试处理大于5 MB的Excel文件时,我仍然会发现内存不足错误。作为参考,我使用的是8 GB RAM的iMac,并且我已经加强了JVM RAM分配,使其达到当前4 GB(一次512 MB)的水平,但没有运气。Apache POI OutOfMemoryError
我正在构建的程序处理目录中的所有Excel电子表格,并将字段中的唯一值添加到HashSet中。所有电子表格处理完成后,生成的HashSet将被写入文件。
无论何时遇到大于5 MB的文件,无论是第一个文件处理还是最后一个文件处理,GC都无法跟上,并且出现内存不足异常。 5 MB似乎是我成功读入和处理excel文件的限制。对我来说这似乎很奇怪,一个刚刚超过5 MB的文件将会严重影响系统的资源,所以我想知道如果问题可能出现在我的代码中?下面的主要方法。思考?
public class Launcher {
public static void main(String[] args) {
WVDataFileReader reader = new WVDataFileReader();
HashSet<String> operators = reader.getOperatorsFromExcel("data/WV/production", 2);
FileOutput.writeToFile(operators, "/db/mysql/mysql-files/operators");
}
}
public abstract class RegulatoryDataFileReader {
private final String EXCEL_EXTENSION = "xlsx";
protected static final Logger LOGGER = Logger.getLogger(RegulatoryDataFileReader.class.getName());
protected abstract HashSet<String> processSheetForOperators(Sheet sheet, int firstDataRow, HashSet<String> set);
public HashSet<String> getOperatorsFromExcel(String directory, int firstDataRow) {
HashSet<String> temp = new HashSet<>();
ArrayList<File> spreadsheets = getExcelFiles(directory);
Collections.sort(spreadsheets);
for (File excelFile : spreadsheets) {
System.out.println("Reading data from " + excelFile.getName());
try {
Workbook workbook = WorkbookFactory.create(excelFile);
Sheet sheet = workbook.getSheetAt(0); // Assumes spreadsheet has 1 sheet
processSheetForOperators(sheet, firstDataRow, temp);
workbook.close();
} catch (FileNotFoundException e) {
LOGGER.log(Level.SEVERE, e.toString(), e);
} catch (IOException e) {
LOGGER.log(Level.SEVERE, e.toString(), e);
} catch (InvalidFormatException e) {
LOGGER.log(Level.SEVERE, e.toString(), e);
}
}
return temp;
}
public class WVDataFileReader extends RegulatoryDataFileReader {
@Override
public HashSet<String> processSheetForOperators(Sheet sheet, int firstDataRow, HashSet<String> set) {
Iterator<Row> rowIterator = sheet.iterator();
if (rowIterator.hasNext()) {
// Skip to the first row containing data
for (int i = 1; i < firstDataRow; i++) {
rowIterator.next();
}
while (rowIterator.hasNext()) {
int columnNum = 0;
Row row = rowIterator.next(); // Advance row
Iterator<Cell> cellIterator = row.cellIterator();
while (cellIterator.hasNext()) {
columnNum++;
Cell cell = cellIterator.next(); // Advance cell
switch (columnNum) {
case 4:
cell.setCellType(Cell.CELL_TYPE_STRING);
String operator = cell.getStringCellValue();
operator = StrUtils.cleanString(operator);;
set.add(operator);
break;
default:
break;
}
}
}
}
return set;
}
}
POI处理usermodel API *中的'xlsx'文件的方式非常低效。不像'xls',它是用poi特定的代码处理的,'xlsx'文件是用一些通用的xml处理的,oo库将每个数据项都加入到一个对象中,封装了一个昂贵的DOM树。如果您只想迭代内容,您可以查看POI的流API,[本页]末尾的表(https://poi.apache.org/spreadsheet/)比较了这些方法。 – Holger
感谢您的信息!我无法相信用户模式可能效率低下 - 这很荒谬。我的xlsx文件有大约50,000行38个数字列+ 1个字符串列(平均)包含大约20个字符。就原始数据而言,单元数据本身应该自己消耗略少于20MB的内存。对我来说这似乎很奇怪,Apache POI将需要几GB的开销来包装这么少量的数据,这就是为什么我认为这个错误可能在我身上。 – Coop