为什么Apache poi的Workbook.close()方法将内容写入输入文件?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么Apache poi的Workbook.close()方法将内容写入输入文件?相关的知识,希望对你有一定的参考价值。

Apache poi的文档(版本3.17)说

void close()

抛出java.io.IOException

关闭从中读取工作簿的基础输入资源(文件或流)。

我的代码从模板文件创建工作簿,对其执行某些操作并将其写入新文件。模板文件应保持不变。但是当我调用close()方法时,文件的更改方式与输出文件相同。

有人可以解释一下吗?在close()方法中是否有类似内置的write()调用?这是一个错误还是一个功能?

到目前为止我的解决方案是放弃close()调用,但不知何故感觉不完整。

    String inPath = "/home/elmicha/test/template.xlsx";
    String outPath = "/home/elmicha/test/out.xlsx";

    try {
        Workbook xlsxFile = WorkbookFactory.create(new File(inPath));

        xlsxFile.getSheetAt(0).createRow(0).createCell(0).setCellValue("test");

        try (FileOutputStream pOuts = new FileOutputStream(outPath)) {
            xlsxFile.write(pOuts);

        xlsxFile.close();

        }

    } catch (IOException | InvalidFormatException | EncryptedDocumentException ex) {
        //...
    }
答案

这很不寻常。我不明白为什么会写入模板文件。这当然不是我的经验。你可以试试:

  • 使用FileInputStream而不是File使其无法写入模板文件。
  • 使用try-with-resources自动关闭Workbook

这是一个例子:

String inPath = "/home/elmicha/test/template.xlsx";
String outPath = "/home/elmicha/test/out.xlsx";

try (Workbook xlsxFile = WorkbookFactory.create(new FileInputStream(inPath))) {
    xlsxFile.getSheetAt(0).createRow(0).createCell(0).setCellValue("test");

    try (FileOutputStream pOuts = new FileOutputStream(outPath)) {
        xlsxFile.write(pOuts);
    }

} catch (IOException | InvalidFormatException | EncryptedDocumentException ex) {
    //...
}

也许:

String inPath = "/home/elmicha/test/template.xlsx";
String outPath = "/home/elmicha/test/out.xlsx";

try (Workbook xlsxFile = WorkbookFactory.create(new FileInputStream(inPath));
    FileOutputStream pOuts = new FileOutputStream(outPath)) {

    xlsxFile.getSheetAt(0).createRow(0).createCell(0).setCellValue("test");
    xlsxFile.write(pOuts);


} catch (IOException | InvalidFormatException | EncryptedDocumentException ex) {
    //...
}
另一答案

只有当我们忽略由FileNotFoundException...(permission denied)引起的POIXMLDocument.close时,才能使模板文件只读的“解决方案”。并且我们应该在处理之后将文件设置为可写以供进一步使用。

所以以下内容将起作用:

import org.apache.poi.ss.usermodel.*;

import java.io.File;
import java.io.FileOutputStream;

class ReadAndWriteExcelWorkbook {

 public static void main(String[] args) throws Exception {

  File templatefile = new File("file.xlsx");

  templatefile.setWritable(true);
  try (Workbook workbook = WorkbookFactory.create(templatefile)) { //at this point the file must be writable
  //try (Workbook workbook = WorkbookFactory.create(templatefile, null, true)) { //this will not work

   Sheet sheet = workbook.getSheetAt(0);

   for (int r = 0; r < 10; r++) {
    Row row = sheet.getRow(r);
    if (row == null) row = sheet.createRow(r);
    Cell cell = row.getCell(r);
    if (cell == null) cell = row.createCell(r);
    cell.setCellValue("changed");
   }

   FileOutputStream out = new FileOutputStream("fileNew.xlsx");
   workbook.write(out);
   out.close();

   templatefile.setWritable(false);

  } catch (java.io.FileNotFoundException ioex) {
   ioex.printStackTrace(); //we simply do ignoring this FileNotFoundException
  }

  templatefile.setWritable(true);

 }
}

笔记:

虽然WorkbookFactory.create(templatefile) templatefile必须是可写的,因为它默认为WorkbookFactory.createboolean readOnly设置为false。因此,如果templatefile只在此时设置为只读,那么WorkbookFactory.create(templatefile)就会失败。

我们不能使用WorkbookFactory.create(templatefile, null, true) - 将boolean readOnly设置为true - 因为这将在workbook.write失败,而POIXMLDocument.write同时将更改改为衬垫OPCPackage

以上是关于为什么Apache poi的Workbook.close()方法将内容写入输入文件?的主要内容,如果未能解决你的问题,请参考以下文章

java poi的使用问题

java poi 操作ppt,该怎么解决

使用Apache poi和android的HSSFCellStyle错误

通过 Excel 来认识神器 Apache POI

Apache POI - Java Excel APIs

为什么Apache poi的Workbook.close()方法将内容写入输入文件?