为什么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.create有boolean readOnly
设置为false
。因此,如果templatefile
只在此时设置为只读,那么WorkbookFactory.create(templatefile)
就会失败。
我们不能使用WorkbookFactory.create(templatefile, null, true)
- 将boolean readOnly
设置为true
- 因为这将在workbook.write
失败,而POIXMLDocument.write
同时将更改改为衬垫OPCPackage
。
以上是关于为什么Apache poi的Workbook.close()方法将内容写入输入文件?的主要内容,如果未能解决你的问题,请参考以下文章