我在以下情况得到以下异常newWB.write(fileOut);
:
Exception in thread "main" org.apache.poi.POIXMLException: java.lang.NullPointerException
at org.apache.poi.POIXMLDocument.getProperties(POIXMLDocument.java:168)
at org.apache.poi.POIXMLDocument.write(POIXMLDocument.java:246)
at com.capgemini.toolkit.App.copyAllSheetsAcrossWorkbook(App.java:263)
at com.capgemini.toolkit.App.main(App.java:58)
Caused by: java.lang.NullPointerException
at org.apache.poi.openxml4j.util.ZipSecureFile$ThresholdInputStream.read(ZipSecureFile.java:210)
at com.sun.org.apache.xerces.internal.impl.XMLEntityManager$RewindableInputStream.read(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.setupCurrentEntity(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLVersionDetector.determineDocVersion(Unknown Source)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(Unknown Source)
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(Unknown Source)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(Unknown Source)
at javax.xml.parsers.DocumentBuilder.parse(Unknown Source)
at org.apache.poi.util.DocumentHelper.readDocument(DocumentHelper.java:140)
at org.apache.poi.POIXMLTypeLoader.parse(POIXMLTypeLoader.java:143)
at org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument$Factory.parse(Unknown Source)
at org.apache.poi.POIXMLProperties.(POIXMLProperties.java:78)
at org.apache.poi.POIXMLDocument.getProperties(POIXMLDocument.java:166)
... 3 more
在POI文档中,总是提到File
由于较低的内存消耗而更好地使用对象.这就是为什么我想知道为什么它不能用于File
对象.
对于测试,这是在main方法中运行的唯一方法,我使用了2个新的Excel文件(.xlsx)和一些虚拟数据.
有谁知道为什么它不能与File
对象一起使用?难道我做错了什么?
仅供参考:我正在使用POI 3.16.
1> Axel Richter..:
使用a File
而不是a FileInputStream
来打开a Workbook
导致较低的内存占用量,因为在XSSF
(*.xlsx
)的情况下,ZipPackage将*.xlsx
直接从文件打开而不是将整个ZIP
内容读入内存.
但这也意味着,ZipPackage
文件Workbook
将被打开,直到将被关闭.因此,在Workbook
关闭之前,没有任何东西可以同时写入该文件.因此,由于无法将Workbook
内容写回到Workbook
打开的相同文件中,因此如果您只想从中读取,则使用a File
而不是FileInputStream
打开a Workbook
就可以了Workbook
.但是如果您想要读取和写入同一个文件,它就不起作用.然后FileInputStream
和FileOutputStream
需要.
因此,在您的情况下,您尝试Workbook newWB
从a 读取File
然后使用将其Workbook
写入同一文件
fileOut = new FileOutputStream(newWorkbook);
newWB.write(fileOut);
而文件已经打开.这失败了.
但:
fisNew = new FileInputStream(newWorkbook);
oldWB = WorkbookFactory.create(new File(oldWorkbook));
newWB = WorkbookFactory.create(fisNew);
...
fileOut = new FileOutputStream(newWorkbook);
newWB.write(fileOut);
fileOut.close();
oldWB.close();
newWB.close();
应该管用.
顺便说一句:如果您使用的是a File
,那么您不应该使用FileInputStream
同一个文件.所以不要使用fisOld
.
使用a File
而不是a FileInputStream
来打开a的另一个缺点Workbook
是,当关闭Workbook
并因此隐式关闭底层文件系统时(POIFSFileSystem
在情况下HSSF
和ZipPackage
在情况下XSSF
),文件获得更新的最后修改日期.文件中没有进行任何更改,但文件已打开,新文件已写入文件系统.这就是更新上次修改日期的原因.
编辑2017年9月21日:使用a的缺点File
似乎比首先想象的要大.OPCPackage.close还将所有更改保存到底层OPCPackage
.因此,如果您XSSFWorkbook
要从文件中打开一个文件,然后想要将变换写入另一个文件write(java.io.OutputStream stream)
,那么在关闭文件时也会更改源文件OPCPackage
.只有从那时起write(java.io.OutputStream stream)
使用POIXMLDocument.write调用POIXMLDocumentPart.onSave "保存底层OOXML包中的更改" 时才会出现此问题 .所以在关闭前更新了所有的变化.XSSFWorkbook
OPCPackage
简短示例:
import org.apache.poi.ss.usermodel.*;
import java.io.File;
import java.io.FileOutputStream;
class ReadAndWriteExcelWorkbook {
public static void main(String[] args) throws Exception {
Workbook workbook = WorkbookFactory.create(new File("file.xlsx"));
Sheet sheet = workbook.getSheetAt(0);
Row row = sheet.getRow(0);
if (row == null) row = sheet.createRow(0);
Cell cell = row.getCell(0);
if (cell == null) cell = row.createCell(0);
cell.setCellValue("changed");
FileOutputStream out = new FileOutputStream("fileNew.xlsx");
workbook.write(out);
out.close();
workbook.close();
}
}
此代码后两个文件fileNew.xlsx
以及file.xlsx
被改变.