7

我正在使用 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.<init>(ZipInputStreamZipEntrySource.java:51) ~[poi-ooxml-3.8-20120326.jar:3.8]
at org.apache.poi.openxml4j.opc.ZipPackage.<init>(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.<init>(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
4

5 回答 5

5

使用上述代码的方法只有一个参数——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) {
    }
}

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

Sheet sheet = null;
try {

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

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

于 2012-06-21T21:18:18.853 回答
3

异常表明您的 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);
于 2012-06-21T20:56:02.523 回答
1

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

于 2012-06-21T19:48:17.340 回答
1

我有同样的错误,我刚刚用相同的版本更新了 pom 依赖项。有效。

        <!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>4.1.0</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>4.1.0</version>
        </dependency>
于 2019-06-14T06:15:29.827 回答
-4

使用这个罐子

<dependency>
    <groupId>org.apache.xmlbeans</groupId>
    <artifactId>xmlbeans</artifactId>
    <version>2.3.0</version>
</dependency>
于 2017-12-24T18:54:55.117 回答