在 Java 中将 100 万条记录从 XLS 文件写入 CSV 文件
Write 1 Million record from XLS file to CVS file in Java
我的项目中有一个场景,用户上传了包含 100 万条记录的 XLS 文件,我需要将此 xls 文件转换为 csv 文件,然后 sql 服务器作业将处理 csv 文件。
我有一个将 xls 文件转换为 csv 的过程 - 但是当我在 PCF 中部署此代码时,它开始抛出堆内存错误。我在本地环境中也遇到同样的错误。
代码快照:
String inputFileName = "UserInput.xls";
FileInputStream input_document = new FileInputStream(new File(inputFileName));
Workbook my_xls_workbook = StreamingReader.builder().open(input_document);//this line throws out of memory error.
Sheet sheet = my_xls_workbook.getSheetAt(0);
......剩余代码读取sheet对象并执行转换。
最好为问题附加一些上下文(例如,你有多少内存,你给 JVM 多少内存,你得到的错误)
话虽如此,我暗暗猜测你应该为 JVM 提供更多内存,比如
java .... -Xms4g -Xmx4g ...
有关这些参数的更多详细信息,请参阅此问题 [1]。
[1] What are the -Xms and -Xmx parameters when starting JVM?
您用来将文件加载到工作簿中的方法似乎很急切,即它只会将整个文档读入内存,解析它,然后 return 如果没有,则返回结果' t 运行先内存不足。
但是,在项目的 README 页面上,它们显示了您应该做些什么来避免这种情况:
import com.monitorjbl.xlsx.StreamingReader;
InputStream is = new FileInputStream(new File("/path/to/workbook.xlsx"));
Workbook workbook = StreamingReader.builder()
.rowCacheSize(100) // number of rows to keep in memory (defaults to 10)
.bufferSize(4096) // buffer size to use when reading InputStream to file (defaults to 1024)
.open(is); // InputStream or File for XLSX file (required)
在此之后,遍历工作簿,但不要使用 get(0
) 方法,因为这似乎需要一次将所有工作簿加载到内存中。
for (Sheet sheet : workbook){
System.out.println(sheet.getSheetName());
for (Row r : sheet) {
for (Cell c : r) {
System.out.println(c.getStringCellValue());
}
}
}
你试过这个吗?如果你这样做了,你应该提交一个错误,因为它显然不应该用完所有可用的内存,因为这是现有库的全部意义。
使用easypoi做
try {
FileOutputStream fos = new FileOutputStream("D:/home/excel/ExcelToCsv.test.csv");
ImportParams params = new ImportParams();
params.setTitleRows(1);
CsvExportParams csvExportParams = new CsvExportParams();
IWriter ce = CsvExportUtil.exportCsv(csvExportParams, MsgClient.class, fos);
ExcelImportUtil.importExcelBySax(
new FileInputStream(
new File(FileUtilTest.getWebRootPath("import/BigDataExport.xlsx"))),
MsgClient.class, params, new IReadHandler<MsgClient>() {
private List<MsgClient> list = new ArrayList<>();
@Override
public void handler(MsgClient o) {
list.add(o);
if (list.size() == 10000) {
ce.write(list);
list.clear();
}
}
@Override
public void doAfterAll() {
System.out.println("succcess--------------------------------");
}
});
} catch (Exception e) {
}
我的项目中有一个场景,用户上传了包含 100 万条记录的 XLS 文件,我需要将此 xls 文件转换为 csv 文件,然后 sql 服务器作业将处理 csv 文件。
我有一个将 xls 文件转换为 csv 的过程 - 但是当我在 PCF 中部署此代码时,它开始抛出堆内存错误。我在本地环境中也遇到同样的错误。
代码快照:
String inputFileName = "UserInput.xls";
FileInputStream input_document = new FileInputStream(new File(inputFileName));
Workbook my_xls_workbook = StreamingReader.builder().open(input_document);//this line throws out of memory error.
Sheet sheet = my_xls_workbook.getSheetAt(0);
......剩余代码读取sheet对象并执行转换。
最好为问题附加一些上下文(例如,你有多少内存,你给 JVM 多少内存,你得到的错误)
话虽如此,我暗暗猜测你应该为 JVM 提供更多内存,比如
java .... -Xms4g -Xmx4g ...
有关这些参数的更多详细信息,请参阅此问题 [1]。
[1] What are the -Xms and -Xmx parameters when starting JVM?
您用来将文件加载到工作簿中的方法似乎很急切,即它只会将整个文档读入内存,解析它,然后 return 如果没有,则返回结果' t 运行先内存不足。
但是,在项目的 README 页面上,它们显示了您应该做些什么来避免这种情况:
import com.monitorjbl.xlsx.StreamingReader;
InputStream is = new FileInputStream(new File("/path/to/workbook.xlsx"));
Workbook workbook = StreamingReader.builder()
.rowCacheSize(100) // number of rows to keep in memory (defaults to 10)
.bufferSize(4096) // buffer size to use when reading InputStream to file (defaults to 1024)
.open(is); // InputStream or File for XLSX file (required)
在此之后,遍历工作簿,但不要使用 get(0
) 方法,因为这似乎需要一次将所有工作簿加载到内存中。
for (Sheet sheet : workbook){
System.out.println(sheet.getSheetName());
for (Row r : sheet) {
for (Cell c : r) {
System.out.println(c.getStringCellValue());
}
}
}
你试过这个吗?如果你这样做了,你应该提交一个错误,因为它显然不应该用完所有可用的内存,因为这是现有库的全部意义。
使用easypoi做
try {
FileOutputStream fos = new FileOutputStream("D:/home/excel/ExcelToCsv.test.csv");
ImportParams params = new ImportParams();
params.setTitleRows(1);
CsvExportParams csvExportParams = new CsvExportParams();
IWriter ce = CsvExportUtil.exportCsv(csvExportParams, MsgClient.class, fos);
ExcelImportUtil.importExcelBySax(
new FileInputStream(
new File(FileUtilTest.getWebRootPath("import/BigDataExport.xlsx"))),
MsgClient.class, params, new IReadHandler<MsgClient>() {
private List<MsgClient> list = new ArrayList<>();
@Override
public void handler(MsgClient o) {
list.add(o);
if (list.size() == 10000) {
ce.write(list);
list.clear();
}
}
@Override
public void doAfterAll() {
System.out.println("succcess--------------------------------");
}
});
} catch (Exception e) {
}