【发布时间】:2018-03-02 10:11:14
【问题描述】:
我有一个从 MongoDB 读取的字符串列表(约 20 万行) 然后我想用Java代码将它写入一个excel文件:
public class OutputToExcelUtils {
private static XSSFWorkbook workbook;
private static final String DATA_SEPARATOR = "!";
public static void clusterOutToExcel(List<String> data, String outputPath) {
workbook = new XSSFWorkbook();
FileOutputStream outputStream = null;
writeData(data, "Data");
try {
outputStream = new FileOutputStream(outputPath);
workbook.write(outputStream);
workbook.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void writeData(List<String> data, String sheetName) {
int rowNum = 0;
XSSFSheet sheet = workbook.getSheet(sheetName);
sheet = workbook.createSheet(sheetName);
for (int i = 0; i < data.size(); i++) {
System.out.println(sheetName + " Processing line: " + i);
int colNum = 0;
// Split into value of cell
String[] valuesOfLine = data.get(i).split(DATA_SEPERATOR);
Row row = sheet.createRow(rowNum++);
for (String valueOfCell : valuesOfLine) {
Cell cell = row.createCell(colNum++);
cell.setCellValue(valueOfCell);
}
}
}
}
然后我得到一个错误:
线程“主”java.lang.OutOfMemoryError 中的异常:GC 开销 超出限制 org.apache.xmlbeans.impl.store.Cur$Locations.(Cur.java:497) 在 org.apache.xmlbeans.impl.store.Locale.(Locale.java:168) 在 org.apache.xmlbeans.impl.store.Locale.getLocale(Locale.java:242) 在 org.apache.xmlbeans.impl.store.Locale.newInstance(Locale.java:593) 在 org.apache.xmlbeans.impl.schema.SchemaTypeLoaderBase.newInstance(SchemaTypeLoaderBase.java:198) 在 org.apache.poi.POIXMLTypeLoader.newInstance(POIXMLTypeLoader.java:132) 在 org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRst$Factory.newInstance(未知 来源)在 org.apache.poi.xssf.usermodel.XSSFRichTextString.(XSSFRichTextString.java:87) 在 org.apache.poi.xssf.usermodel.XSSFCell.setCellValue(XSSFCell.java:417) 在 ups.mongo.excelutil.OutputToExcelUtils.writeData(OutputToExcelUtils.java:80) 在 ups.mongo.excelutil.OutputToExcelUtils.clusterOutToExcel(OutputToExcelUtils.java:30) 在 ups.mongodb.App.main(App.java:74)
请给我一些建议?
非常感谢您。
更新解决方案:使用 SXSSWorkbook 代替 XSSWorkbook
public class OutputToExcelUtils {
private static SXSSFWorkbook workbook;
private static final String DATA_SEPERATOR = "!";
public static void clusterOutToExcel(ClusterOutput clusterObject, ClusterOutputTrade clusterOutputTrade,
ClusterOutputDistance ClusterOutputDistance, String outputPath) {
workbook = new SXSSFWorkbook();
workbook.setCompressTempFiles(true);
FileOutputStream outputStream = null;
writeData(clusterOutputTrade.getTrades(), "Data");
try {
outputStream = new FileOutputStream(outputPath);
workbook.write(outputStream);
workbook.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void writeData(List<String> data, String sheetName) {
int rowNum = 0;
SXSSFSheet sheet = workbook.createSheet(sheetName);
sheet.setRandomAccessWindowSize(100); // For 100 rows saved in memory, it will flushed after wirtten to excel file
for (int i = 0; i < data.size(); i++) {
System.out.println(sheetName + " Processing line: " + i);
int colNum = 0;
// Split into value of cell
String[] valuesOfLine = data.get(i).split(DATA_SEPERATOR);
Row row = sheet.createRow(rowNum++);
for (String valueOfCell : valuesOfLine) {
Cell cell = row.createCell(colNum++);
cell.setCellValue(valueOfCell);
}
}
}
}
【问题讨论】:
-
如果可能,不要一次将所有数据保存在内存中。否则让你的 JVM 使用更多内存。
-
你需要excel文件吗?你能生成可以在大多数电子表格中打开的 tsv/csv 文件吗?
-
谢谢亨利,你的想法和下面的亚历克斯一样。因为excel文件有mant sheet所以不能生成为CSV文件。
-
在this SO article 的评论中提到:“SXSSF 分配临时文件,您必须始终通过调用 dispose 方法明确清理。 请参阅 SXSSF documentation.”
标签: java apache-poi