使用Apache POI读取Excel .XLSX时出错

我正在使用Apache POI 3.8库来读取Web应用程序中的XLSX文件。 以下代码在Java控制台应用程序中运行良好:

InputStream inputFS = new FileInputStream("test.xlsx"); Workbook workbook = new XSSFWorkbook(inputFS); // below exception is thrown on this line Sheet sheet = workbook.getSheetAt(0); 

但在Web应用程序中使用时会抛出“读取错误”。 下面粘贴了堆栈跟踪的相关摘录:

 java.io.IOException: Read error at java.io.FileInputStream.readBytes(Native Method) ~[na:1.6.0_31] at java.io.FileInputStream.read(Unknown Source) ~[na:1.6.0_31] at java.io.FilterInputStream.read(Unknown Source) ~[na:1.6.0_31] at java.io.PushbackInputStream.read(Unknown Source) ~[na:1.6.0_31] at java.util.zip.ZipInputStream.readFully(Unknown Source) ~[na:1.6.0_31] at java.util.zip.ZipInputStream.readLOC(Unknown Source) ~[na:1.6.0_31] at java.util.zip.ZipInputStream.getNextEntry(Unknown Source) ~[na:1.6.0_31] at org.apache.poi.openxml4j.util.ZipInputStreamZipEntrySource.(ZipInputStreamZipEntrySource.java:51) ~[poi-ooxml-3.8-20120326.jar:3.8] at org.apache.poi.openxml4j.opc.ZipPackage.(ZipPackage.java:83) ~[poi-ooxml-3.8-20120326.jar:3.8] at org.apache.poi.openxml4j.opc.OPCPackage.open(OPCPackage.java:228) ~[poi-ooxml-3.8-20120326.jar:3.8] at org.apache.poi.util.PackageHelper.open(PackageHelper.java:39) ~[poi-ooxml-3.8-20120326.jar:3.8] at org.apache.poi.xssf.usermodel.XSSFWorkbook.(XSSFWorkbook.java:187) ~[poi-ooxml-3.8-20120326.jar:3.8] at com.corp.ReportManager.parseExcelReport(ReportManager.java:575) [ReportManager.class:na] 

以下JAR包含在类路径中(按相同顺序):

 poi-3.8-20120326.jar poi-ooxml-3.8-20120326.jar poi-ooxml-schemas-3.8-20120326.jar xbean.jar dom4j-1.6.1.jar 

由于我在调用上面的代码之前收集了一些堆利用率统计信息,因此似乎没有与内存相关的问题。 XLSX文件的大小为1.15 MB。

 ##### Heap utilization statistics [MB] ##### Used Memory:13 MB Free Memory:9 MB Total Memory:23 MB Max Memory:247 MB 

使用上面代码的方法有一个参数 – FileInputStream。 代码片段中的第一行是代码的一部分,但是调用方法的一部分。 由于所讨论的方法不了解Excel格式甚至文件扩展名以进行有根据的猜测,我决定首先尝试使用HSSF API读取FileInputStream,如下所示:

 Sheet sheet = null; try { POIFSFileSystem poifs = new POIFSFileSystem(inputFS); Workbook workbook = new HSSFWorkbook(poifs); sheet = workbook.getSheetAt(0); } catch (Exception e) { } if (sheet == null) { try { Workbook workbook = new XSSFWorkbook(inputFS); sheet = workbook.getSheetAt(0); } catch (Exception e) { } } 

上面代码的问题是在第二次尝试通过XSSF API打开它时inputFS对象的状态是未知的。 这产生了read error 。 我用以下代码替换了上面的代码,它工作正常,问题似乎得到解决:

 Sheet sheet = null; try { Workbook workbook = WorkbookFactory.create(inputFS); sheet = workbook.getSheetAt(0); } catch (Exception e) { } 

我使用XLS(较旧的,二进制)和XLSX(较新的,基于XML的)格式对其进行了测试,并且它可以工作。 感谢大家的帮助和投入!

exception表明您的InputStream存在问题。 但是,如果您有一个文件,那么直接将其传递给POI! 使用InputStream需要将所有内容缓冲到内存中,从而占用空间。 既然你不需要做那个缓冲,不要! 无论如何,避免缓冲应该解决你的问题

如果您使用最新的每晚POI版本运行,那么它非常简单。 您的代码变为:

 File file = new File("test.xlsx"); OPCPackage opcPackage = OPCPackage.open(file); XSSFWorkbook workbook = new XSSFWorkbook(opcPackage); 

否则,它非常相似:

 File file = new File("test.xlsx"); OPCPackage opcPackage = OPCPackage.open(file.getAbsolutePath()); XSSFWorkbook workbook = new XSSFWorkbook(opcPackage); 

如果您不确定您的文件是HSSFWorkbook还是XSSFWorkbook,那么您可以使用WorkbookFactory为您打开相应的文件:

 File file = new File("test.xlsx"); Workbook workbook = WorkbookFactory.create(file); 

看起来你需要使用他们的XSSF API

用这个jar子

  org.apache.xmlbeans xmlbeans 2.3.0