即使执行fileoutputstream.close()

时间:2019-05-29 10:29:20

标签: java excel apache-poi

我正在尝试基于通用模板生成新的Excel文件。我正在打开模板excel文件,对其进行编辑并将其保存在新位置。要写入文件,我正在使用FileOutputStream,并且在写入后将其关闭以保存它。整个过程正常工作,但是新创建的Excel文件未正确保存。我的模板文件为35kb,而我新创建的Excel文件仅显示30kb。当打开新创建的excel文件时,可以看到写入的数据,需要保存并关闭它以反映正确的36kb大小。
直接将30kb未保存的excel直接上传到外部应用程序时,必须将新的excels上传到显示“未找到数据”的外部应用程序,而成功保存36kb的文件才能成功上传文件。

我尝试了Internet上建议的各种不同方法来做同样的事情,但没有一个可以生成正确的excel文件。我正在使用Java 1.7和apache-poi 3.17版。

以下是我的代码的示例:-

public void createExcelFiles() throws ParseException, IOException {

    File file = new File(ExcelTemplatePath);
    FileInputStream fip = new FileInputStream(file);
    FileOutputStream fos = new FileOutputStream(excelOutputFile);

    XSSFWorkbook workbookOld = new XSSFWorkbook(fip);
    try (SXSSFWorkbook workbook = new SXSSFWorkbook(workbookOld, rowAccessWindowSize)) {

        if (makeLargeFiles) {
            SXSSFSheet sheet = (SXSSFSheet) workbook.getSheetAt(0);
            makeExcelFile.makeLargeFile(sheet);
            workbook.write(fos);
        } else {
            Sheet sheet = workbookOld.getSheetAt(0);
            makeExcelFile.makeNormalFile(sheet);
            workbookOld.write(fos);

        }
        fos.close();
        fip.close();
        workbook.close();
    }
    workbookOld.close();

}

2 个答案:

答案 0 :(得分:0)

XSSFWorkbook这样的包装好的I / O流应该首先关闭,可能仍然向包装的OutputStream写一个结尾。而且底层流可能会关闭。

请记住,某些包装类将自己在自己的close内部关闭包装的流。

由于try-with-resources是理想的,因此也可以在发生异常时关闭,最终版本为:

public void createExcelFiles() throws ParseException, IOException {
    File file = new File(ExcelTemplatePath);
    try (FileInputStream fip = new FileInputStream(file);
            FileOutputStream fos = new FileOutputStream(excelOutputFile);
            XSSFWorkbook workbookOld = new XSSFWorkbook(fip);
            SXSSFWorkbook workbook = new SXSSFWorkbook(workbookOld, rowAccessWindowSize)) {

        if (makeLargeFiles) {
            SXSSFSheet sheet = (SXSSFSheet) workbook.getSheetAt(0);
            makeExcelFile.makeLargeFile(sheet);
            workbook.write(fos);
        } else {
            Sheet sheet = workbookOld.getSheetAt(0);
            makeExcelFile.makeNormalFile(sheet);
            workbookOld.write(fos);

        }
    }
    // Doing in reverse order of declaration:
    // 1. workbook.close();
    // 2. workbookOld.close();
    // 3. fos.close();
    // 4. fip.close();
}

在您的代码中有一个逆转,并且关闭是通过try-with-resources显式发生的。

答案 1 :(得分:0)

已使用excel的共享字符串属性解决了此问题。我更新了工作簿构造函数调用,如下所示:

SXSSFWorkbook工作簿=新的SXSSFWorkbook(workbookOld,rowAccessWindowSize,true,true)

第二个true参数用于共享字符串的使用。使用此属性可使数据对外部应用程序可见,而无需再次打开并保存它。但是,大小问题仍然存在,为什么使用共享字符串仍然有效仍不清楚。 有关共享字符串的更多信息,请查看this