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) {
//...
}
答案 0 :(得分:3)
这很不寻常。我不明白为什么要写模板文件。这当然不是我的经历。你可以尝试:
FileInputStream
代替File
,无法写入模板文件。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) {
//...
}
答案 1 :(得分:0)
"解决方案"使模板文件只读是只有在我们忽略由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
同时将更改提交到底层{{}}时会失败{ {1}}。