有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java ApachePOI即使在执行fileoutputstream之后也不保存excel工作簿。关闭()

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

我尝试了互联网上建议的各种不同方法来做同样的事情,但没有一种方法能够生成正确的excel文件。我使用的是Java1.7和ApachePOI版本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) 个答案

  1. # 1 楼答案

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

    SXSSFWorkbook工作簿=新SXSSFWorkbook(workbookOld,RowAccessWindowsSize,true,true)

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

  2. # 2 楼答案

    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进行的