为什么我无法阻止 Apache POI 更改源文件?

Jos*_*hDM 2 java excel apache-poi

我正在使用 Apache POI 工作簿在 Java 中打开 Excel 文件(源),更改特定单元格中的数据,将工作簿保存到单独的文件,然后关闭工作簿(因为文档指出要关闭工作簿,甚至如果它是只读的)。

POI 每次都会更改源 Excel 文件中的数据。根据 POI 文档的建议,我尝试了几种不同的方法来防止这种情况发生,但这些方法都失败了。

这里有两种尝试,理论上应该可行,但实际上却行不通。

尝试 1 - 将源文件设置为只读

File file = new File("{path-to-existing-source-file}");

file.setReadOnly();

Workbook workbook = WorkbookFactory.create(file); // throws a FileNotFoundException
Run Code Online (Sandbox Code Playgroud)

“访问FileNotFoundException被拒绝”被抛出WorkbookFactory.create(file)

java.io.FileNotFoundException: {path-to-source-file-that-exists} (Access is denied)
at java.io.RandomAccessFile.open0(Native Method)
at java.io.RandomAccessFile.open(RandomAccessFile.java:316)
at java.io.RandomAccessFile.<init>(RandomAccessFile.java:243)
at org.apache.poi.poifs.nio.FileBackedDataSource.newSrcFile(FileBackedDataSource.java:158)
at org.apache.poi.poifs.nio.FileBackedDataSource.<init>(FileBackedDataSource.java:60)
at org.apache.poi.poifs.filesystem.POIFSFileSystem.<init>(POIFSFileSystem.java:224)
at org.apache.poi.poifs.filesystem.POIFSFileSystem.<init>(POIFSFileSystem.java:172)
at org.apache.poi.ss.usermodel.WorkbookFactory.create(WorkbookFactory.java:298)
at org.apache.poi.ss.usermodel.WorkbookFactory.create(WorkbookFactory.java:271)
at org.apache.poi.ss.usermodel.WorkbookFactory.create(WorkbookFactory.java:252)
at com.stackoverflow.MyClass(MyClass.java:71)
Run Code Online (Sandbox Code Playgroud)

源文件存在,并且它是有效的只读文件。

尝试 2 - 使用允许显式设置只读的 POI API 构造函数

File file = new File("{path-to-existing-source-file}");
Workbook workbook = WorkbookFactory.create(file, null, true);  // true is read-only

// dataBean is just a container bean with the appropriate reference values
Sheet sheet = workbook.getSheet(dataBean.getSheetName());
Row row = sheet.getRow(dataBean.getRowNumber());
Cell cell = row.getCell(dataBean.getColumnNumber());
cell.setCellValue(dataBean.getValue());

// target is another File reference
OutputStream outStream = new FileOutputStream(new File("path-to-target-file"));
workbook.write(outStream);   // throws InvalidOperationException
Run Code Online (Sandbox Code Playgroud)

InvalidOperationException在 write 调用期间抛出一个异常:

Caused by: org.apache.poi.openxml4j.exceptions.InvalidOperationException: 
Operation not allowed, document open in read only mode!
at org.apache.poi.openxml4j.opc.OPCPackage.throwExceptionIfReadOnly(OPCPackage.java:551)
at org.apache.poi.openxml4j.opc.OPCPackage.removePart(OPCPackage.java:955)
at org.apache.poi.openxml4j.opc.PackagePart.getOutputStream(PackagePart.java:531)
at org.apache.poi.xssf.usermodel.XSSFWorkbook.commit(XSSFWorkbook.java:1770)
at org.apache.poi.ooxml.POIXMLDocumentPart.onSave(POIXMLDocumentPart.java:463)
at org.apache.poi.ooxml.POIXMLDocument.write(POIXMLDocument.java:236)
at com.stackoverflow.MyClass(MyClass.java:90)
Run Code Online (Sandbox Code Playgroud)

“不允许操作,文档以只读模式打开!”。当然是设置为只读;我不想写入源,我只想将所有数据发送到新目标。

使用 POI 时,我可以设置或更改什么来不改变来源?

我们当前的解决方法是创建重复的源文件,但这不是一个好的解决方案。

Bas*_*sen 6

我遇到了同样的问题并通过使用 aFileInputStream而不是 a解决了它File

Workbook workbook = WorkbookFactory.create(file);
Run Code Online (Sandbox Code Playgroud)

变成:

Workbook workbook = WorkbookFactory.create(new FileInputStream(file));
Run Code Online (Sandbox Code Playgroud)