2016-02-14 79 views
2

我正在使用Apache POI 3.13并试图从给定的模板文件中搜索和替换文本,然后保存新生成的.docx。这里是我的代码:Java如何避免在搜索和替换Apache POI时覆盖模板文件

public static void main(String[] args) throws InvalidFormatException, IOException { 
    String filePath = "Sample.docx"; 
    File outputfile = new File("SampleProcessed.docx"); 

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

    for (XWPFParagraph p : doc.getParagraphs()) { 
     List<XWPFRun> runs = p.getRuns(); 
     if (runs != null) { 
      for (XWPFRun r : runs) { 
       String text = r.getText(0); 
       if (text != null && text.contains("$VAR")) { 
        text = text.replace("$VAR", "JohnDoe"); 
        r.setText(text, 0); 
       } 
      } 
     } 
    } 

    doc.write(new FileOutputStream(outputfile)); 
    doc.close(); 
    System.out.println("Done"); 
    Desktop.getDesktop().open(outputfile); 
} 

这看起来很简单,但是当我运行此代码,“Sample.docx”的文件也被替换。最后,我有两个具有相同内容的文档。

这是POI的正常行为吗?我认为打开文档只会将其加载到内存中,然后执行'doc.write(OutputStream);'会将其刷新到磁盘。

我试图写入相同的'文件路径',但正如所料,它会引发异常,因为我试图写入当前打开的文件。

唯一有效的工作是当我先复制模板文件并改为使用该副本。但是现在,我有3个文件,第一个是原始模板“Sample.docx”,其余2个文件的内容相同(SampleProcessed.docx和SampleProcessedOut.docx)。

它的工作,但它是很浪费。有什么办法吗?我做错了什么,也许我打开错误的文字?

回答

4

由于您使用

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

创建XWPFDocument,一个OPCPackagefilePathREAD_WRITE模式打开。如果这将被关闭,它也将被保存。见https://poi.apache.org/apidocs/org/apache/poi/openxml4j/opc/OPCPackage.html#close%28%29

OPCPackage将被关闭,而XWPFDocument将被关闭。

但是,为什么你这样做呢?为什么不是

XWPFDocument doc = new XWPFDocument(new FileInputStream(filePath)); 

与此XWPFDocument将在内存中创建只有一个新的OPCPackage没有关系的文件。

+0

这工作!谢谢!我错过了。对不起,我应该事先阅读文档。我认为OPCPackage是打开.docx文件的唯一方法。再次感谢! – yev

+0

还有一个open()的版本,它有一个参数PackageAccess,您可以在其中指定READ作为开放模式,从而避免写回数据,请参阅https://poi.apache.org/apidocs/org/ apache/poi/openxml4j/opc/OPCPackage.html#open(java.io.File,%20org.apache.poi.openxml4j.opc.PackageAccess) – centic

+0

@centic:你试过这个吗?如果OPCPackage被打开,你将如何改变'Run'中的文本? –