【问题标题】:Java Apache POI : Read / Write from .doc file issueJava Apache POI:从 .doc 文件读取/写入问题
【发布时间】:2017-03-25 15:43:42
【问题描述】:

我正在编写代码来读取 .doc 文件作为模板,并在各种迭代后将数据写入新的 .doc 文件中。我的代码似乎有一些我无法弄清楚的简单问题。

下面是我写的代码,[我只在stackoverflow的某个地方得到了基本骨架。]

public class HWPFTest {

  public static void main(String[] args) {
        String inputFile = "F:\\docx\\input.doc";
        String outputFile = "F:\\docx\\output.doc";
        POIFSFileSystem fs = null;

        try {
              for (int i = 0; i < 3; i++) {
                    fs = new POIFSFileSystem(new FileInputStream(inputFile));
                    HWPFDocument doc = new HWPFDocument(fs);
                    System.out.println("LOOOOOOOOOOOOP ----> " + i);
                    doc = replaceText(doc, "$count", String.valueOf(i));
                    doc = replaceText(doc, "$filename", "FileName" + i);
                    doc = replaceText(doc, "$inputFile", "Input" + i);
                    doc = replaceText(doc, "$outputFile", "Output" + i);
                    doc = replaceText(doc, "$message", "Message" + i);
                    doc = replaceText(doc, "$snap", "Snapshot" + i);
                    saveWord(outputFile, doc);
              }
              System.out.println("DONE...");
        }
        catch (FileNotFoundException e) {
              e.printStackTrace();
        } catch (IOException e) {
              e.printStackTrace();
        }
  }

  private static HWPFDocument replaceText(HWPFDocument doc, String findText, String replaceText) {
        Range r1 = doc.getRange();
        for (int i = 0; i < r1.numSections(); ++i) {
              Section s = r1.getSection(i);
              for (int x = 0; x < s.numParagraphs(); x++) {
                    Paragraph p = s.getParagraph(x);
                    for (int z = 0; z < p.numCharacterRuns(); z++) {
                          CharacterRun run = p.getCharacterRun(z);
                          String text = run.text();
                          if (text.contains(findText)) {
                               run.replaceText(findText, replaceText);
                               System.out.println("findText: " + findText + " replaceText: " + replaceText);
                          }
                    }
              }
        }
        return doc;
  }


  private static void saveWord(String filePath, HWPFDocument doc) throws FileNotFoundException, IOException {
        FileOutputStream out = null;
        try {
              // Add true to make the data append possible in output stream.
              out = new FileOutputStream(filePath, true);
              doc.write(out);
              out.flush();
        } catch (Exception ex) {
              ex.printStackTrace();
        } finally {
              out.close();
        }
  }

}

代码运行没有任何问题。这是 input.doc 的外观,

运行成功后,也会生成output.doc。但问题是它只包含第一个循环的数据。

理想情况下,它应该包含所有 3 次迭代的数据,但它只包含第一次的数据,然后什么都没有。它在执行期间也不会显示任何错误/异常。我还确保 outputstream 的 append 选项为 true。

这是 output.doc 的外观,

不确定,我做错了什么。

当我运行程序时,我可以在下面的输出中看到,

LOOOOOOOOOOOOP ----> 0 findText: $count replaceText: 0 findText: $filename replaceText: FileName0 findText: $inputFile replaceText: Input0 findText: $outputFile replaceText: Output0 findText: $message replaceText: Message0 findText: $snap replaceText: Snapshot0 LOOOOOOOOOOOOP ----> 1 findText: $count replaceText: 1 findText: $filename replaceText: FileName1 findText: $inputFile replaceText: Input1 findText: $outputFile replaceText: Output1 findText: $message replaceText: Message1 findText: $snap replaceText: Snapshot1 LOOOOOOOOOOOOP ----> 2 findText: $count replaceText: 2 findText: $filename replaceText: FileName2 findText: $inputFile replaceText: Input2 findText: $outputFile replaceText: Output2 findText: $message replaceText: Message2 findText: $snap replaceText: Snapshot2 DONE...

因为我在每次迭代中都将输入文件初始化为新文件。所以我确实在迭代期间找到了所有 $ 元素。只是它们没有附加到最终文件中。

有人可以帮忙吗?非常感谢。

【问题讨论】:

    标签: java file-io apache-poi fileoutputstream doc


    【解决方案1】:

    您正在打开模板文件,更改内容并保存到“F:\docx\output.doc”。您这样做 3 次,每次覆盖输出文件。

    在循环中准备字符串然后在文档中只替换一次会更好。您的 main 方法如下所示:

    public static void main(String[] args) {
            String inputFile = "F:\\docx\\input.doc";
            String outputFile = "F:\\docx\\output.doc";
            POIFSFileSystem fs = null;
    
            String counts = "";
    
            try {
                for (int i = 0; i < 3; i++) {
                    counts += String.valueOf(i) + "; ";
                }
                fs = new POIFSFileSystem(new FileInputStream(inputFile));
                HWPFDocument doc = new HWPFDocument(fs);
                doc = replaceText(doc, "$count", counts);
                saveWord(outputFile, doc);
            }
            catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    

    【讨论】:

    • 我在上面添加了我在运行程序时看到的控制台输出。它还表明 $ 元素被找到并被每次迭代替换。
    • 是的,我错了)您正在打开模板文件,更改内容并保存到“F:\\docx\\output.doc”。您这样做 3 次,每次覆盖输出文件。因此,请尝试我在回答中为您提供的解决方案。
    • 实际上我所显示的内容是虚拟内容,为了简单起见,每个人都可以阅读。实际内容将是带有路径的文件名,并且在文件名或文件路径中也将包含特殊字符。因此,如果我尝试将其添加到字符串中,它将因此而中断。我现在拥有的,完美无缺。唯一的问题是我不知道 POI 中有任何方法可以帮助我将所有迭代的内容附加到单个文件中。您是否知道任何其他可能有效的技术。
    【解决方案2】:

    显然而且令人惊讶的是,Apache POI 没有任何方法可以通过 append 写入现有的 word 文档。所以上面的方法是行不通的。

    我也试过 Apache FileUtils,但它没有保留 word 文档的格式。我也尝试过 docx4j,但它只适用于 docx 文件,并且它的合并实用程序类是付费的。

    还有另一个框架 Aspose Words,它提供了更好的控制和灵活性。它允许您将内容附加到现有文档,限制为 1150 个字符。但这对于我的要求来说太过分了,因为我的写作没有超过设定的限制。

    所以我用它来实现我想做的事情。终于成功了。

    感谢@D 的帮助。克劳昌卡

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-06-05
      • 2017-10-14
      • 2018-09-06
      • 1970-01-01
      • 2015-06-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多