在 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) {

    }

地址https://github.com/jueyue/easypoi