java解析doc、docx内容踩坑日记

前段时间有一个客户遇到了一件很奇怪的事情,他在使用程序解析一批word文件时 , 程序在运行一段时间后总是会自动中断 , 他查看了导致中断的word文档,发现也能正常打开,当他把文件另存为后,再运行程序发现程序就可以正常往下运行了 。他感觉很奇怪,就找我来帮他分析一下原因 。

一、问题分析(以下日志和代码均是重现问题后输出的)

首先登录服务器,找到程序的运行日志,打开当天运行的日志文件,查看是否有错误日志 , 果然发现了错误日志,具体内容如下:
java.lang.IllegalArgumentException: The document is really a OOXML fileat org.apache.poi.hwpf.HWPFDocumentCore.verifyAndBuildPOIFS(HWPFDocumentCore.java:123)at org.apache.poi.hwpf.extractor.WordExtractor.(WordExtractor.java:51)at com.file.util.readword.redWordText(Test.java:25)at com.file.util.readword.main(Test.java:77)
根据错误日志不难分析出是解析doc文件报错了,根据错误日志可以直接定位到错位代码所在位置,通过反编译工具可以查看它的源码,源码具体如下(看到下面的代码 , 小伙伴们是否确定了问题的原因了?):
public static String redWordText(String filePath){File file=new File(filePath);String fileName=file.getName();//获取文件名String suffix = fileName.substring(fileName.indexOf("."), fileName.length());//获取文件后缀String text="";InputStream is = null;try {is = new FileInputStream(filePath);if (StringUtils.equals(suffix, ".doc")) {// 解析doc文件WordExtractor ex = new WordExtractor(is);text = ex.getText();ex.close();} else if (StringUtils.equals(suffix, ".docx")) {// 解析docx文件XWPFDocument doc = new XWPFDocument(is);XWPFWordExtractor extractor = new XWPFWordExtractor(doc);text = extractor.getText();extractor.close();}} catch (Exception e) {e.printStackTrace();}finally {if (is != null) {try {is.close();} catch (IOException e) {e.printStackTrace();}}}return text;}
当我看到源码后,基本确定了问题出现的原因 。

二、原因分析

客户收集上来的文件,渠道是多样的,有些docx文件的后缀被强制修改成了doc后缀,这些修改后的文件还是可以正常打开的 。当使用StringUtils.equals(suffix, ".doc")这种直接判断后缀的方式来判断文件类型是返回true的,导致docx文件使用了doc的解析方式 , 所以报错了 。

三、解决办法

针对上面的问题可以使用FileMagic.valueOf(is) == FileMagic.OLE2来判断是否是doc格式文件,具体实现代码如下:
public static String redWordText1(String filePath){String text = "";InputStream is = null;try {is = new FileInputStream(filePath);if (FileMagic.valueOf(is) == FileMagic.OLE2) {WordExtractor ex = new WordExtractor(is);text = ex.getText();ex.close();} else if (FileMagic.valueOf(is) == FileMagic.OOXML) {XWPFDocument doc = new XWPFDocument(is);XWPFWordExtractor extractor = new XWPFWordExtractor(doc);text = extractor.getText();extractor.close();}} catch (Exception e) {e.printStackTrace();} finally {if (is != null) {try {is.close();} catch (IOException e) {e.printStackTrace();}}}return text;}

四、其他存在的问题

当客户收集的文件的后缀被改成了大写 , 这种直接判断后缀的方法就无法判断了,需要在判断前把后缀统一成小写 。

五、总结

【java解析doc、docx内容踩坑日记】通过上面的分析,小伙伴们以后判断word、excel文件格式时 , 一定要注意尽量避免直接使用后缀直接判断,推荐使用org.apache.poi.poifs.filesystem.FileMagic类进行判断(ps:专业的事情交给专业的来处理),否则一不小心就挖坑 , 导致后面的小伙伴又得加班填坑了 。#头号有新人#

相关经验推荐