read excel file(which is in classpath ) vi

2019-02-14 04:33发布

问题:

I am trying to read (using apache poi) .xlsx file which is not in file system but in classpath. I am using maven - so it is in resources folder.

my code is -

InputStream resourceAsStream = MyReader.class.getClassLoader().getResourceAsStream("test.xlsx");
   Workbook wb = new XSSFWorkbook(resourceAsStream);

I am getting this exception.

Caused by: java.lang.IllegalArgumentException: MALFORMED
        at java.util.zip.ZipCoder.toString(ZipCoder.java:58) ~[?:1.7.0_51]
        at java.util.zip.ZipInputStream.readLOC(ZipInputStream.java:297) ~[?:1.7.0_51]
        at java.util.zip.ZipInputStream.getNextEntry(ZipInputStream.java:121) ~[?:1.7.0_51]
        at org.apache.poi.openxml4j.util.ZipInputStreamZipEntrySource.<init>(ZipInputStreamZipEntrySource.java:51) ~[poi
a3]
        at org.apache.poi.openxml4j.opc.ZipPackage.<init>(ZipPackage.java:88) ~[poi-ooxml-3.11-beta3.jar:3.11-beta3]
        at org.apache.poi.openxml4j.opc.OPCPackage.open(OPCPackage.java:272) ~[poi-ooxml-3.11-beta3.jar:3.11-beta3]
        at org.apache.poi.util.PackageHelper.open(PackageHelper.java:37) ~[poi-ooxml-3.11-beta3.jar:3.11-beta3]

When I read same file from file system everything is fine. Is there a bug in my code or do I miss understand something?

UPDATE1: This is in web app, so code is deployed in tomcat 7.

UPDATE2: when I read same file in this way - it works.

File file = new File("C:\\Users\\.....\\test.xlsx");
 FileInputStream fileInputStream = new FileInputStream(file);

 Workbook wb = new XSSFWorkbook(fileInputStream);

thanks

回答1:

After spending days on this problem I found an answer in stackoverflow )). FileInputStream vs ClassPathResource vs getResourceAsStream and file integrity

the problem in maven-resources-plugin filtering, it corrupts excel file .

You should not filter binary files like excel and use two mutually exclusive resource sets as described at the bottom of this page 

maven resources plugin



回答2:

Adding more information to @user1321466 answer, to filter you can do as described in maven resources plugin site:

If you have both text files and binary files as resources it is recommended to have two separated folders. One folder src/main/resources (default) for the resources which are not filtered and another folder src/main/resources-filtered for the resources which are filtered.

or just exclude the files from filtering:

<resource>
    <directory>src/main/resources</directory>
    <filtering>true</filtering>
    <excludes>
        <exclude>**/*.xsd</exclude>
        <exclude>**/*.xml</exclude>
    </excludes>
</resource>
<resource>
    <directory>src/main/resources</directory>
    <filtering>false</filtering>
    <includes>
        <include>**/*.xsl</include>
        <include>**/*.xslx</include>
    </includes>
</resource>


回答3:

Is the file at the top of the classpath, i.e. in WEB-INF/classes?

The API doc for Classloader.getResource() says the resource name is:

"The name of a resource is a '/'-separated path name that identifies the resource."

So if your file is in some subdirectory, that path should be part of the resource name.