Apache POI报错:Unexpected end of ZLIB input stream 同文件写入求助
解决Apache POI写入原Word文档时的ZLIB输入流异常问题
你遇到的核心问题是:直接向正在读取的原Word文档写入修改内容时,触发Unexpected end of ZLIB input stream异常,但写入新路径文件时正常。
问题原因
.docx本质是ZIP压缩包格式,当你用OPCPackage.open(DocX)打开原文件时,POI会持续占用文件进行读取操作;同时用FileOutputStream写入同一个文件,会直接覆盖原文件内容,导致POI后续读取压缩包数据时,拿到的是被破坏的不完整压缩结构,最终触发ZLIB解压异常。
解决方案
方案一:先读取到内存,释放原文件后再写入
先将原文件内容加载到内存中的XWPFDocument,立即关闭输入流释放文件占用,之后再写入原文件:
public class WordEdit { static String DocX; static String DocX2; public static void main(String[] args) throws Exception { DocX = "C:\\Users\\aneesh.shaik\\Downloads\\I&TF-0206-2024.docx"; DocX2 = "D:\\Automation\\Files\\I&TF-0206-2024.docx"; // 读取原文件到内存,随即关闭OPCPackage释放文件 OPCPackage opcPackage = OPCPackage.open(DocX); XWPFDocument doc = new XWPFDocument(opcPackage); opcPackage.close(); // 执行文本替换逻辑 for (XWPFTable tbl : doc.getTables()) { for (XWPFTableRow row : tbl.getRows()) { for (XWPFTableCell cell : row.getTableCells()) { for (XWPFParagraph p : cell.getParagraphs()) { for (XWPFRun r : p.getRuns()) { String text = r.getText(0); if (text != null && text.contains("Aneesh423")) { text = text.replace("Aneesh423", "Aneesh"); System.out.println("find 2"); r.setText(text,0); } } } } } } // 写入原文件,此时文件已被释放 doc.write(new FileOutputStream(DocX)); doc.close(); } }
方案二:写入临时文件后替换原文件(更安全)
先将修改内容写入临时文件,确认写入成功后,再替换原文件——这种方式能避免写入过程出错导致原文件损坏:
public class WordEdit { static String DocX; static String DocX2; public static void main(String[] args) throws Exception { DocX = "C:\\Users\\aneesh.shaik\\Downloads\\I&TF-0206-2024.docx"; DocX2 = "D:\\Automation\\Files\\I&TF-0206-2024.docx"; XWPFDocument doc = new XWPFDocument(OPCPackage.open(DocX)); // 执行文本替换逻辑 for (XWPFTable tbl : doc.getTables()) { for (XWPFTableRow row : tbl.getRows()) { for (XWPFTableCell cell : row.getTableCells()) { for (XWPFParagraph p : cell.getParagraphs()) { for (XWPFRun r : p.getRuns()) { String text = r.getText(0); if (text != null && text.contains("Aneesh423")) { text = text.replace("Aneesh423", "Aneesh"); System.out.println("find 2"); r.setText(text,0); } } } } } } // 写入临时文件 File tempFile = new File(DocX + ".tmp"); doc.write(new FileOutputStream(tempFile)); doc.close(); // 替换原文件 File originalFile = new File(DocX); if (originalFile.delete() && tempFile.renameTo(originalFile)) { System.out.println("原文件替换成功"); } else { System.err.println("替换原文件失败"); // 可在此添加失败后的补救逻辑,比如保留临时文件 } } }
内容的提问来源于stack exchange,提问作者Aneesh Ahamed
相关产品推荐
相关产品推荐

