You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Apache POI操作已有Word文档:新增/覆盖表格及报错解决

解决Apache POI写入Word文档时的ZLIB输入流异常

错误原因

直接对同一个文件同时执行读和写操作,OPCPackage.open打开文件后会占用文件资源,此时用FileOutputStream写入会破坏文件的压缩结构,触发EOFException: Unexpected end of ZLIB input stream异常。

解决方案

核心思路是避免读写同一文件的冲突,先将原文档读取到内存,再写入临时文件,最后替换原文件;同时处理原有内容的清除,实现第二页表格的覆盖更新。

修正后的代码

import org.apache.poi.xwpf.usermodel.*;
import org.apache.poi.openxml4j.opc.OPCPackage;
import java.io.*;

public class WordTableUpdater {
    public static void main(String[] args) {
        String sourceFile = "Testword.docx";
        String tempFile = "Temp_Testword.docx";

        try (OPCPackage pkg = OPCPackage.open(new FileInputStream(sourceFile));
             XWPFDocument doc = new XWPFDocument(pkg);
             FileOutputStream outStream = new FileOutputStream(tempFile)) {

            // 清除第二页及之后的原有内容(包括表格)
            boolean isAfterPageBreak = false;
            // 倒序遍历,避免索引偏移
            for (int i = doc.getBodyElements().size() - 1; i >= 0; i--) {
                IBodyElement element = doc.getBodyElements().get(i);
                if (isAfterPageBreak) {
                    doc.removeBodyElement(i);
                    continue;
                }
                // 检查段落是否包含分页符
                if (element instanceof XWPFParagraph) {
                    XWPFParagraph para = (XWPFParagraph) element;
                    for (XWPFRun run : para.getRuns()) {
                        if (run.getCTR().getBrList().stream()
                                .anyMatch(br -> br.getType() == org.openxmlformats.schemas.wordprocessingml.x2006.main.STBrType.PAGE)) {
                            isAfterPageBreak = true;
                            break;
                        }
                    }
                }
            }

            // 如果首页没有分页符,添加一个确保表格在第二页
            if (!isAfterPageBreak) {
                XWPFParagraph pageBreakPara = doc.createParagraph();
                XWPFRun run = pageBreakPara.createRun();
                run.addBreak(BreakType.PAGE);
            }

            // 创建新表格
            XWPFTable table = doc.createTable();

            // 构建第一行
            XWPFTableRow row1 = table.getRow(0);
            row1.getCell(0).setText("col one, row one");
            row1.addNewTableCell().setText("col two, row one");
            row1.addNewTableCell().setText("col three, row one");

            // 构建第二行
            XWPFTableRow row2 = table.createRow();
            row2.getCell(0).setText("col one, row two");
            row2.getCell(1).setText("col two, row two");
            row2.getCell(2).setText("col three, row two");

            // 构建第三行
            XWPFTableRow row3 = table.createRow();
            row3.getCell(0).setText("col one, row three");
            row3.getCell(1).setText("col two, row three");
            row3.getCell(2).setText("col three, row three");

            // 写入临时文件
            doc.write(outStream);

            // 替换原文件
            File original = new File(sourceFile);
            File temp = new File(tempFile);
            if (original.delete() && temp.renameTo(original)) {
                System.out.println("表格更新完成");
            } else {
                System.err.println("替换原文件失败,请检查文件权限");
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

关键改动说明

  1. 读写分离:用FileInputStream读取原文档,写入临时文件后再替换原文件,彻底避免资源冲突
  2. 清除原有内容:倒序遍历文档元素,找到分页符后移除后续所有内容,实现覆盖更新
  3. 自动资源管理:使用try-with-resources语法自动关闭流,防止资源泄漏
  4. 确保分页:如果首页没有分页符,自动添加一个,保证表格生成在第二页

内容的提问来源于stack exchange,提问作者Jeet

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 08:50:38