我编写了一个程序,该程序可以打开Microsoft Word文档进行读写。
该程序读取Word的段落和表格并替换占位符。运行后,程序会将文档保存在与读取的文件路径相同的文件路径中。
如果使用此选项打开文档,则会收到NullPointerException:
String filePath = "...";
XWPFDocument doc = new XWPFDocument(OPCPackage.open(filePath));
// Replace paragraphs.
doc.write(new FileOutputStream(filePath));
doc.close();
这是堆栈跟踪:
java.lang.NullPointerException
at org.apache.poi.POIXMLDocument.getProperties(POIXMLDocument.java:147)
at org.apache.poi.POIXMLDocument.write(POIXMLDocument.java:225)
Caused by: java.lang.NullPointerException
at org.apache.poi.openxml4j.util.ZipSecureFile$ThresholdInputStream.read(ZipSecureFile.java:211)
at org.apache.xerces.impl.XMLEntityManager$RewindableInputStream.readAndBuffer(Unknown Source)
at org.apache.xerces.impl.XMLEntityManager.setupCurrentEntity(Unknown Source)
at org.apache.xerces.impl.XMLVersionDetector.determineDocVersion(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
at org.apache.xerces.parsers.DOMParser.parse(Unknown Source)
at org.apache.xerces.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:163)
at org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument$Factory.parse(Unknown Source)
at org.apache.poi.POIXMLProperties.<init>(POIXMLProperties.java:78)
at org.apache.poi.POIXMLDocument.getProperties(POIXMLDocument.java:145)
如果我使用此选项:
String filePath = "...";
InputStream fis = new FileInputStream(filePath);
XWPFDocument doc = new XWPFDocument(OPCPackage.open(fis));
// Replace paragraphs.
doc.write(new FileOutputStream(filePath));
doc.close();
正常工作。 我试图将文档保存在其他路径中,这种情况可以正常工作。
因此,当我使用open(String path)
方法打开Word文档时,为什么我会收到一条错误消息。
OPCPackage.open(InputStream in)和OPCPackage.open(String path)方法之间有什么区别?为什么我会有NullPointerException?
答案 0 :(得分:1)
public static OPCPackage open(java.io.InputStream in)指出:
打开一个包装。注意-使用的内存比open(String)多得多, 不需要将整个zip文件保存在内存中,并且可以 本地方法的优势
那是什么意思? public static OPCPackage open(java.lang.String path)和public static OPCPackage open(java.io.File file)
都直接从*.docx
文件打开ZipPackage文件系统。与使用public static OPCPackage open(java.io.InputStream in)
首先将ZIP
文件系统读入内存的InputStream
相比,它使用的内存更少。但是另一方面,*.docx
文件现在也已打开,每次尝试在打开的文件中写入内容都会导致错误(多种不同,并不总是NPE,对我而言,java.io.EOFException: Unexpected end of ZLIB input stream
使用的是{ {1}} [1]),只要写入操作不仅真正写入打开的apache poi 4.0.1
文件系统,还写入打开的ZIP
文件。
[1]:经过测试,我在Windows 10上使用*.docx
得到了您的NPE。UbuntuLinux崩溃了。
结论:
直接从apache poi 3.17
打开OPCPackage
(ZipPackage
),然后写入另一个File
是可行的。直接从File
打开OPCPackage
,然后写入相同的File
不起作用。
对于在File
中使用ZipPackage
处理的所有Office Open XML文件格式都是如此。
要获得在创建apache poi
时使用较少内存的优势,因为使用了XWPFDocument
而不是File
,但是仍然能够写入同一文件,我们可以使用文件的临时副本,如下所示:
InputStream
当然,这是使用额外文件存储的缺点,即使是临时的。