Apache POI操作Excel的坑

Apache POI操作Excel的坑
强烈推介IDEA2021.1.3破解激活,IntelliJ IDEA 注册码,2021.1.3IDEA 激活码 

大家好,我是架构君,一个会写代码吟诗的架构师。今天说一说Apache POI操作Excel的坑,希望能够帮助大家进步!!!

本文记录一下用Apache POI操作Excel时可能遇到一些坑。

excel版本错误

首先是excel版本问题,由于office excel 03版和07版的区别,在读取文件时如果版本不匹配会报以下错误。

 

org.apache.poi.poifs.filesystem.NotOLE2FileException: Invalid header signature; read 0x0010000000060809, expected 0xE11AB1A1E011CFD0 - Your file appears not to be a valid OLE2 document at org.apache.poi.poifs.storage.HeaderBlock.<init>(HeaderBlock.java:167) at org.apache.poi.poifs.storage.HeaderBlock.<init>(HeaderBlock.java:106) at org.apache.poi.poifs.filesystem.POIFSFileSystem.<init>(POIFSFileSystem.java:137) at org.apache.poi.hssf.usermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:382) at org.apache.poi.hssf.usermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:364)

最初解决办法是根据文件名采用不同的Workbook来初始化stream,大致代码如下,请忽视判断逻辑不严谨的问题(这里应该取后缀名而不是判断包含)。

 

 if (filePath.indexOf(".xlsx") != -1) { XSSFWorkbook wb = new XSSFWorkbook(inputStream); return wb.getSheetAt(sheetIndex); } else { HSSFWorkbook wb = new HSSFWorkbook(inputStream); return wb.getSheetAt(sheetIndex); }

手动修改文件名后不匹配

通过上面的方法大部分还是可以解决的,但是遇到人为改变后缀名后会出现如下异常。

 

Caused by: org.apache.poi.openxml4j.exceptions.InvalidFormatException: Package should contain a content type part [M1.13] at org.apache.poi.openxml4j.opc.ZipPackage.getPartsImpl(ZipPackage.java:203) at org.apache.poi.openxml4j.opc.OPCPackage.getParts(OPCPackage.java:684) at org.apache.poi.openxml4j.opc.OPCPackage.open(OPCPackage.java:275) at org.apache.poi.util.PackageHelper.open(PackageHelper.java:37)

再次优化一下,使用工厂模式创建Workbook:

 

Workbook workbook = WorkbookFactory.create(inputStream);

看一下POI的源码:

 

public static Workbook create(InputStream inp, String password) throws IOException, InvalidFormatException, EncryptedDocumentException { InputStream is = FileMagic.prepareToCheckMagic(inp); FileMagic fm = FileMagic.valueOf(is); switch(fm) { case OLE2: NPOIFSFileSystem fs = new NPOIFSFileSystem(is); return create(fs, password); case OOXML: return new XSSFWorkbook(OPCPackage.open(is)); default: throw new InvalidFormatException("Your InputStream was neither an OLE2 stream, nor an OOXML stream"); } }

可以看到他是根据stream类型来初始化的,这样即使人为改变文件名也无关紧要。

stream类型错误

通过上面的方式处理后,有时候还是会出现以下异常:

 

org.apache.poi.openxml4j.exceptions.InvalidFormatException: Your InputStream was neither an OLE2 stream, nor an OOXML stream at org.apache.poi.ss.usermodel.WorkbookFactory.create(WorkbookFactory.java:186) at org.apache.poi.ss.usermodel.WorkbookFactory.create(WorkbookFactory.java:149) at com.github.crab2died.ExcelUtils.readExcel2Objects(ExcelUtils.java:126) at com.github.crab2died.ExcelUtils.readExcel2Objects(ExcelUtils.java:206)

这个问题可能是文件传输stream为非可读性的stream,解决方法为将读取的stream转为ByteArrayInputStream再读取:

 

InputStream is = new ByteArrayInputStream(xlsxInByteArray);

然而笔者是直接读取本地文件,并非此类问题,以下解答给了笔者答案,直接文件另存为后再读取新的文件,问题解决。

https://stackoverflow.com/questions/29894185/your-inputstream-was-neither-an-ole2-stream-nor-an-ooxml-stream-while-reading

如果文件很多,直接在程序中先另写一个文件再读取新文件即可,目前没有找到更好的解决方案。

 

本文来源huayang183,由架构君转载发布,观点不代表Java架构师必看的立场,转载请标明来源出处:https://javajgs.com/archives/18018

发表评论