【发布时间】:2014-11-12 18:40:17
【问题描述】:
我找到了很多如何使用 Java 将 XLSX 转换为 CSV 文件的解决方案,所有解决方案都使用:XSSFWorkbook。我面临的问题是流可能包含太多数据。我只是不明白为什么,文件只有 4mb。
代码:
// For storing data into CSV files
StringBuffer data = new StringBuffer();
try {
FileOutputStream fos = new FileOutputStream(outputFile);
System.out.println("Getting input stream.");
// Get the workbook object for XLS file
XSSFWorkbook workbook = new XSSFWorkbook(new FileInputStream(inputFile));
System.out.println(" - Done");
// Get first sheet from the workbook
XSSFSheet sheet = workbook.getSheetAt(0);
Cell cell;
Row row;
// Iterate through each rows from first sheet
Iterator<Row> rowIterator = sheet.iterator();
System.out.println(" - Reading xlsx rows.");
while (rowIterator.hasNext()) {
i++;
row = rowIterator.next();
// For each row, iterate through each columns
Iterator<Cell> cellIterator = row.cellIterator();
while (cellIterator.hasNext()) {
cell = cellIterator.next();
switch (cell.getCellType()) {
case Cell.CELL_TYPE_BOOLEAN:
data.append(cell.getBooleanCellValue() + ";");
break;
case Cell.CELL_TYPE_NUMERIC:
data.append(cell.getNumericCellValue() + ";");
break;
case Cell.CELL_TYPE_STRING:
data.append(cell.getStringCellValue() + ";");
break;
case Cell.CELL_TYPE_BLANK:
data.append("" + ";");
break;
default:
data.append(cell + ";");
}
}
data.append('\n');
int limit = 10000;
if ((i % limit) == 0) {
System.out.println(" - Writing " + limit + " data.");
fos.write(data.toString().getBytes());
fos.flush();
data = null;
data = new StringBuffer();
System.out.println(" - Data written.");
}
}
fos.write(data.toString().getBytes());
fos.flush();
fos.close();
错误指向 switch 语句中的行,我在其中向数据 (StringBuffer) 附加了一些内容,但我将其置空,所以它不应该成为问题。
【问题讨论】:
-
你在
StringBuffer里塞东西,这可能效率不高。为什么还要将它存储在内存中?只需创建一行,将其写入文件并继续(您可能想使用BufferedWriter。另外,为什么要创建一个字符串并将其转换为byte[],下一个复制内存占用。取决于速度在你的 JVM 和 GC 中,你会得到很多额外的对象。尝试和开始的一件事是降低你的限制,而不是构造一个新的StringBuffer只是清空并重用它。而不是StringBUffer我建议使用StringBuilder。 -
是的,在我使用 setLength(0) 之前,问题不存在,它是在 fileInputStream 期间。
-
大型对象可能会徘徊,因此重用可能会更好。它在阅读时发生的事实并不意味着它是因为阅读。你的记忆正在填满,大的
StringBuffer将是我的第一个修复。另一个注意事项是您正在使用StringBuffer但仍在使用 String concat 添加字符串。我建议从您的案例陈述中删除+ ";",并在案例陈述之后添加data.append(';')。保存为 concat 创建额外的字符串。