Java, как избежать перезаписи файла шаблона при выполнении поиска и замены в Apache POI

Я использую Apache POI 3.13 и пытался найти и заменить текст из данного файла шаблона, а затем сохранил новый сгенерированный.docx. Вот мой код:

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);' сбросит его на диск.

Я попытался записать в тот же файл filePath, но, как и ожидалось, он выдает исключение, поскольку я пытаюсь записать в текущий открытый файл.

Единственное, что сработало, это когда я сначала скопировал файл шаблона и использовал его вместо этого. Но теперь у меня есть 3 файла, первый из которых был исходным шаблоном 'Sample.docx', а остальные 2 имеют одинаковое содержимое (SampleProcessed.docx и SampleProcessedOut.docx).

Это сработало, но довольно расточительно. Есть ли способ к этому? Я делаю что-то не так, возможно, я неправильно открываю слово document?

1 ответ

Решение

Так как вы используете

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

создать XWPFDocument, OPCPackage открывается из filePath в READ_WRITE Режим. Если это будет закрыто, оно также будет сохранено. См. https://poi.apache.org/apidocs/org/apache/poi/openxml4j/opc/OPCPackage.html.

OPCPackage будет закрыт, пока XWPFDocument будет закрыто.

Но почему ты так делаешь? Почему бы и нет

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

?

С этим XWPFDocument будет создан в памяти только с новым OPCPackage без отношения к файлу.

Другие вопросы по тегам