我有一个Word文档(docx);我想对该文档进行更改并将结果另存为另一个文件,而保留原始文件。我有以下代码说明我当前的问题:
package sandbox.word.doccopy;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
public class CopyTest
{
public static void main(String[] args) throws Exception
{
String sourceFilename = "CopyTestSource.docx";
String destinationFilename = "CopyTestResult.docx";
CopyTest docCopy = new CopyTest();
docCopy.copyTesting(sourceFilename, destinationFilename);
System.out.println("done");
}
public void copyTesting(String source, String destination)
throws IOException, InvalidFormatException
{
XWPFDocument doc = new XWPFDocument(OPCPackage.open(source));
// for each paragraph that has runs,
// put an exclamation at the end of the first run.
for (XWPFParagraph par : doc.getParagraphs())
{
List<XWPFRun> runs = par.getRuns();
if (runs.size() > 0)
{ XWPFRun run = par.getRuns().get(0);
String text = run.getText(0);
text = text + "!";
run.setText(text, 0);
}
}
// FileOutputStream fos = new FileOutputStream(destination);
// doc.write(fos);
// fos.close();
doc.close();
}
}
Run Code Online (Sandbox Code Playgroud)
我可以通过三种方式运行它,更改类文件底部的注释行。如您所见,有三行使用目标文件名创建文件输出流、写入并关闭它,还有一行仅关闭当前文档。
如果我注释掉 3 行并保留 1 行,则不会向当前文档写入任何更改(当然,也不会创建副本文档)。
如果我将所有 4 行保留为未注释,则会创建包含更改的副本文档,并且这些更改也会写入源文档。
如果我注释掉第四行,我会得到一个经过更改的目标文档,而源文档保持不变。
最后一个是我想要的,我可以编写我的代码来做到这一点。但我希望在更改后关闭文档会更改它或不更改它,并且更改它不取决于我是否已将更改写入另一个文件。
任何人都可以阐明这一点吗?
罪魁祸首是这样的XWPFDocument doc = new XWPFDocument(OPCPackage.open(source));:特别是这个:OPCPackage.open(source)。
当static OPCPackage open(java.lang.String path)时,从具有读/写权限的OPCPackage文件路径的底层文件中打开。path另外,它与底层文件保持直接连接。这可以节省一些内存,但也有缺点,正如您现在所看到的。
所有更改均XWPFDocument在此进行OPCPackage,但首先在随机存取存储器中进行。
在调用doc.writePOIXMLDocument.write (java.io.OutputStream stream)时,首先OPCPackage更新底层。然后更改OPCPackage将通过给定的 保存在目标文档中OutputStream stream。因此,如果不调用,doc.write文件中的任何内容都不会发生更改,而只会保留在随机存取存储器中。
然后,当doc.close()被调用时, OPCPackage.close也会被调用。这将关闭打开的可写包并保存其内容。由于OPCPackage直接连接到底层文件,因此它将内容保存到该文件中。这就是为什么更改也会写入源文档的原因。
这应该可以解释你的观察结果。
还XWPFDocument提供构造函数
XWPFDocument(java.io.InputStream is)。这在内部调用OPCPackage.open(java.io.InputStream in)。这将打开OPCPackage来自InputStream. thenOPCPackage仅位于随机存取存储器中,并且独立于源文件。这会使用更多内存,因为整体OPCPackage需要位于随机存取内存中,但OPCPackage.close不会导致源文件发生更改。
所以我要做的是:
...
XWPFDocument doc = new XWPFDocument(new FileInputStream(source));
...
FileOutputStream fos = new FileOutputStream(destination);
doc.write(fos);
fos.close();
doc.close();
...
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
586 次 |
| 最近记录: |