今天在使用POI,XWPFDocument处理word文档时报错了。错误如下。
org.apache.poi.EmptyFileException: The supplied file was empty (zero bytes long)
at org.apache.poi.util.IOUtils.peekFirstNBytes(IOUtils.java:112)
at org.apache.poi.poifs.filesystem.FileMagic.valueOf(FileMagic.java:209)
at org.apache.poi.openxml4j.opc.internal.ZipHelper.verifyZipHeader(ZipHelper.java:143)
at org.apache.poi.openxml4j.opc.internal.ZipHelper.openZipStream(ZipHelper.java:175)
at org.apache.poi.openxml4j.opc.ZipPackage.<init>(ZipPackage.java:104)
at org.apache.poi.openxml4j.opc.OPCPackage.open(OPCPackage.java:312)
at org.apache.poi.ooxml.util.PackageHelper.open(PackageHelper.java:47)
at org.apache.poi.xwpf.usermodel.XWPFDocument.<init>(XWPFDocument.java:123)
我也试图通过网络寻找解决方法,很可惜的是一无所获,网上所写的和我遇到的问题不一样,虽然报错可能是一样的。让我感到很困惑的是,我调用的是以前写的一个接口,以前是没有问题的,单独去测试这个接口也是没有问题。没办法,只能自己一步步调试跟踪了,最终还是找到了问题所在。看看如下代码。
public void findMatchsInWord(InputStream inputStream) throws IOException {
XWPFDocument xwpfDocument = new XWPFDocument(inputStream);
for (XWPFParagraph xwpfParagraph : xwpfDocument.getParagraphs()) {
for (XWPFRun xwpfRun : xwpfParagraph.getRuns()) {
logger.info(xwpfRun.text());
}
}
}
看这代码好像是没有问题的,调用也不会报错误。像下面这样去调用呢。
for(int i = 1;i < 3;i++){
findMatchsInWord(inputStream);
}
第一轮循环的时候是没有问题的,第二轮循环的时候就报错了。
为什么会出现这种情况呢?
new XWPFDocument(inputStream)这段代*会码**从inputStream读取内容,而且会把内容全部读取完。第二次循环到这段代码的时候也会从inputStream里面读取内容,但是是接着上一次读取结束的位置开始读取的,由于第一次循环已经把inputStream里面的内容读取完了,第二次读取的时候里面就没有内容,就报错了。
如何解决这个问题,如何在循环中使用new XWPFDocument(inputStream)?
既然知道了原因那就好办了,只要每次传进XWPFDocument是新的inputStream不就可以了嘛。
看看下面的调用代码。
ByteArrayOutputStream byteArrayOutputStream = ObjectUtils.isEmpty(inputStream)?null: toByteArrayOutputStream(inputStream);
for(int i = 1;i < 3;i++){
findMatchsInWord(new ByteArrayInputStream(byteArrayOutputStream.toByteArray()));
}
toByteArrayOutputStream函数的实现代码
public ByteArrayOutputStream toByteArrayOutputStream(InputStream inputStream) throws BusinessException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try {
byte[] buffer = new byte[1024];
int len;
while ((len = inputStream.read(buffer)) > -1) {
byteArrayOutputStream.write(buffer, 0, len);
}
byteArrayOutputStream.flush();
} catch (IOException e) {
throw new BusinessException(e);
}finally {
}
return byteArrayOutputStream;
}
至此,这个问题就解决了。
有问题欢迎反馈,大家一起交流学习!