用Java将100万条记录从XLS文件写入CVS文件

用Java将100万条记录从XLS文件写入CVS文件,java,excel,heap,file-conversion,pcf,Java,Excel,Heap,File Conversion,Pcf,在我的项目中,我有一个场景,用户上载的XLS文件记录为1百万,我需要将此XLS文件转换为csv文件,然后sql server作业将处理csv文件 我有一个将xls文件转换为csv的过程——但当我在PCF中部署此代码时,它开始抛出堆内存erorr。我在本地环境中也遇到了同样的错误 代码快照: String inputFileName = "UserInput.xls"; FileInputStream input_document = new FileInputStream(new File(i

在我的项目中,我有一个场景,用户上载的XLS文件记录为1百万,我需要将此XLS文件转换为csv文件,然后sql server作业将处理csv文件

我有一个将xls文件转换为csv的过程——但当我在PCF中部署此代码时,它开始抛出堆内存erorr。我在本地环境中也遇到了同样的错误

代码快照:

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);

。。。。。。重新生成代码读取工作表对象并执行转换。

最好在问题上附加一点上下文(例如,您有多少内存,给JVM多少内存,您得到的错误)

话虽如此,我的想法是应该给JVM更多的内存,比如

java .... -Xms4g -Xmx4g ...
有关这些参数的更多详细信息,请参见问题[1]



[1] 使用以下代码:

InputStream is = new FileInputStream(new File("UserInput.xls"));
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)

更多信息参见

将文件加载到工作簿中的方法似乎很迫切,即它只需将整个文档读入内存,对其进行解析,然后返回结果(如果没有首先耗尽内存)

但是,在项目页面上,它们显示了您应该做什么来避免:

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());
        }
    }
}
你试过这个吗?如果您这样做了,您应该提交一个bug,因为它显然不应该耗尽所有可用内存,因为这是现有库的全部要点。

使用easypoi do

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

    }
试试看{
FileOutputStream fos=新的FileOutputStream(“D:/home/excel/exceltosv.test.csv”);
ImportParams参数=新的ImportParams();
参数设置标题(1);
CsvExportParams CsvExportParams=新的CsvExportParams();
IWriter ce=CsvExportUtil.exportCsv(csvExportParams,MsgClient.class,fos);
ExcelImportUtil.importExcelBySax(
新文件输入流(
新文件(FileUtilTest.getWebRootPath(“import/BigDataExport.xlsx”),
MsgClient.class,参数,新的IReadHandler(){
私有列表=新的ArrayList();
@凌驾
公共无效处理程序(MsgClient o){
列表。添加(o);
如果(list.size()==10000){
行政长官(名单);
list.clear();
}
}
@凌驾
公营部门{
System.out.println(“成功----------------------”;
}
});
}捕获(例外e){
}

地址

StreamingReader不在Java标准库中。。。请提供理解您的代码所需的完整类名(或导入)。请尝试使用
open(File)
而不是
open(InputStream)
@Andreas。这不会有帮助,运行的是相同的代码。。。查看源代码:好的,那么,尝试直接使用POI,以获得良好的数据流读取。是的。。。这个库OP使用的似乎是将整个东西加载到内存中,所以这个名字很糟糕,因为它意味着你可以进行流解析(除了下一个元素外,不会将任何东西加载到内存中),但是你真的不能从我在源代码中看到的内容。你好,Renato-我刚刚尝试了你的代码,它对我有效。我的问题解决了。你说得对-我在内存中加载了整个文件。使用缓存大小,我能够解决这个问题。@Bharat该代码与我在同一时间发布,并且来自自述文件。另外,该用户是一个新用户,我提供了更多关于为什么情况对他不利的信息。我解释了他使用库的方式如何触发它立即将数据加载到内存中,这是他似乎没有意识到的。另外,另一个答案是不够的:您必须通过迭代器进行迭代,如上所示。当用户使用get(0)时,仍将加载内存中的所有数据。请善意地取消否决票。