Java ApachePOI Word文档打开时出现NullPointerException

Java ApachePOI Word文档打开时出现NullPointerException,java,apache,ms-word,apache-poi,Java,Apache,Ms Word,Apache Poi,我编写了一个程序,可以打开MicrosoftWord文档进行读写 该程序读取单词段落和表格,并替换占位符。运行后,程序将文档保存在与读取相同的文件路径 如果使用此选项打开文档,则会出现NullPointerException: String filePath = "..."; XWPFDocument doc = new XWPFDocument(OPCPackage.open(filePath)); // Replace paragraphs. doc.write(new FileOutput

我编写了一个程序,可以打开MicrosoftWord文档进行读写

该程序读取单词段落和表格,并替换占位符。运行后,程序将文档保存在与读取相同的文件路径

如果使用此选项打开文档,则会出现NullPointerException:

String filePath = "...";
XWPFDocument doc = new XWPFDocument(OPCPackage.open(filePath));
// Replace paragraphs.
doc.write(new FileOutputStream(filePath));
doc.close();
以下是stacktrace:

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)
工作正常。 我试图将文档保存在另一个路径中,这种情况可以正常工作

因此,我不明白为什么在使用
open(stringpath)
方法打开Word文档时会收到错误消息

OPCPackage.open(InputStream in)和OPCPackage.open(String path)方法之间有什么区别?为什么我会有NullPointerException?

状态:

打开一个包裹。注意-使用的内存比打开的(字符串)内存要多得多, 它不需要将整个zip文件保存在内存中,并且可以 本地方法的优势

那是什么意思?以及
publicstaticopcpackage open(java.io.File文件)
都是直接从
*.docx
文件打开文件系统。它使用的内存少于
publicstaticopcpackage open(java.io.InputStream in)
首先使用
InputStream将
ZIP
文件系统读入内存的内容。但另一方面,
*.docx
文件现在也打开了,每次尝试向打开的文件中写入内容都会导致错误(多个不同的,不一定是NPE,对我来说它是
java.io.EOFException:使用
ApachePOI4.0.1
[1]的ZLIB输入流意外结束)只要写入操作不仅写入打开的
ZIP
文件系统,而且写入打开的
*.docx
文件

[1] :刚刚测试过,我在Windows10上使用ApachePOI3.17获得了您的NPE。Ubuntu Linux只是崩溃了

结论:

直接从
文件
打开
OPCPackage
ZipPackage
),然后写入另一个
文件
即可。直接从
文件
打开
OPCPackage
,然后写入同一
文件
不起作用

这适用于所有使用
apache poi
中的
ZipPackage
处理的Office Open XML文件格式

为了在创建
XWPFDocument
时使用更少的内存,因为使用
文件
而不是
输入流
,并且能够写入同一文件,我们可以使用文件的临时副本,如下所示:

import java.io.FileOutputStream;
import java.io.File;

import java.nio.file.Paths;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;

import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.openxml4j.opc.OPCPackage;

public class WordReadAndReWrite {

 public static void main(String[] args) throws Exception {

  String filePath = "WordDocument.docx";
  String tmpFilePath = "~$WordDocument.docx";

  File file = Files.copy(Paths.get(filePath), Paths.get(tmpFilePath), StandardCopyOption.REPLACE_EXISTING).toFile();

  XWPFDocument doc = new XWPFDocument(OPCPackage.open(file));

  // Replace paragraphs.

  FileOutputStream out = new FileOutputStream(filePath); 
  doc.write(out);
  out.close();
  doc.close();

  Files.deleteIfExists(Paths.get(tmpFilePath));
 }

}

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

可能与@Zephyr重复:并非所有NPE都是Q/a的重复。在这里,NPE是从
ApachePOI
库深处的类抛出的。因此,必须允许询问为什么会发生这种情况。否则,使用库就完全过时了,因为每个用户都必须深入挖掘库的内部,才能了解NPE发生的原因。@AxelRichter-I,无可否认,没有仔细检查堆栈跟踪。我撤回了投票决定结束投票。谢谢:)
import java.io.FileOutputStream;
import java.io.File;

import java.nio.file.Paths;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;

import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.openxml4j.opc.OPCPackage;

public class WordReadAndReWrite {

 public static void main(String[] args) throws Exception {

  String filePath = "WordDocument.docx";
  String tmpFilePath = "~$WordDocument.docx";

  File file = Files.copy(Paths.get(filePath), Paths.get(tmpFilePath), StandardCopyOption.REPLACE_EXISTING).toFile();

  XWPFDocument doc = new XWPFDocument(OPCPackage.open(file));

  // Replace paragraphs.

  FileOutputStream out = new FileOutputStream(filePath); 
  doc.write(out);
  out.close();
  doc.close();

  Files.deleteIfExists(Paths.get(tmpFilePath));
 }

}