Apache Poi Word文档的打开给出了NullPointerException

时间:2019-02-08 22:17:13

标签: java apache ms-word apache-poi

我编写了一个程序,该程序可以打开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?

1 个答案:

答案 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打开OPCPackageZipPackage),然后写入另一个File是可行的。直接从File打开OPCPackage,然后写入相同的File不起作用。

对于在File中使用ZipPackage处理的所有Office Open XML文件格式都是如此。

要获得在创建apache poi时使用较少内存的优势,因为使用了XWPFDocument而不是File,但是仍然能够写入同一文件,我们可以使用文件的临时副本,如下所示:

InputStream

当然,这是使用额外文件存储的缺点,即使是临时的。