Java Apache POI:从 .doc 文件读取/写入问题
Java Apache POI : Read / Write from .doc file issue
我正在编写代码以读取 .doc 文件作为模板,并在多次迭代后将数据写入新的 .doc 文件。我的代码似乎有一些我无法弄清楚的简单问题。
下面是我写的代码,[我只在 Whosebug 的某个地方得到了基本框架。]
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 的追加选项为真。
这是 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...
因为我在每次迭代中都将输入文件初始化为新文件。所以我确实在迭代过程中找到了所有 $ 元素。只是它们没有附加到最终文件中。
有人可以帮忙吗?非常感谢。
您正在打开模板文件,更改内容并保存到 "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();
}
}
显然和令人惊讶的是,Apache POI 没有任何方法可以通过附加到现有的 word 文档来编写。所以上面的方法是行不通的。
我也试过Apache FileUtils,但是它不保留word文档的格式。我也试过 docx4j,但只适用于 docx 文件,而且它的合并实用程序 class 是付费的。
还有另一个框架 Aspose Words,它提供了更好的控制和灵活性。它允许您将内容附加到现有文档,限制为 1150 个字符。但这对我来说太过分了,因为我的写作没有超过设定的限制。
所以我用它来实现我想做的事情。终于成功了。
感谢@D 的帮助。克劳尚卡
我正在编写代码以读取 .doc 文件作为模板,并在多次迭代后将数据写入新的 .doc 文件。我的代码似乎有一些我无法弄清楚的简单问题。
下面是我写的代码,[我只在 Whosebug 的某个地方得到了基本框架。]
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 的追加选项为真。
这是 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...
因为我在每次迭代中都将输入文件初始化为新文件。所以我确实在迭代过程中找到了所有 $ 元素。只是它们没有附加到最终文件中。
有人可以帮忙吗?非常感谢。
您正在打开模板文件,更改内容并保存到 "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();
}
}
显然和令人惊讶的是,Apache POI 没有任何方法可以通过附加到现有的 word 文档来编写。所以上面的方法是行不通的。
我也试过Apache FileUtils,但是它不保留word文档的格式。我也试过 docx4j,但只适用于 docx 文件,而且它的合并实用程序 class 是付费的。
还有另一个框架 Aspose Words,它提供了更好的控制和灵活性。它允许您将内容附加到现有文档,限制为 1150 个字符。但这对我来说太过分了,因为我的写作没有超过设定的限制。
所以我用它来实现我想做的事情。终于成功了。
感谢@D 的帮助。克劳尚卡