Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java NIO ZipFileSystem: "zip END header not found" while creating file system

Tags:

java

zip

nio

I'm asking this here because googling this error only gives me hits on writing a zip file, while I'm only trying to read it.
I have a unit test where I'm trying to test the following production code:

Map<String, String> zipProps = new HashMap<>();
URI zipUri = URI.create("jar:file:" + itemZipPath.toString());
try (FileSystem zipfiles = FileSystems.newFileSystem(zipUri, zipProps)) {
   // do stuff...
} catch (IOException e) {
   // log an error
}

However this fails on the line containing the try:

java.util.zip.ZipError: zip END header not found
at com.sun.nio.zipfs.ZipFileSystem.zerror(ZipFileSystem.java:1605)
at com.sun.nio.zipfs.ZipFileSystem.findEND(ZipFileSystem.java:1021)
at com.sun.nio.zipfs.ZipFileSystem.initCEN(ZipFileSystem.java:1030)
at com.sun.nio.zipfs.ZipFileSystem.<init>(ZipFileSystem.java:130)
at com.sun.nio.zipfs.ZipFileSystemProvider.newFileSystem(ZipFileSystemProvider.java:117)
at java.nio.file.FileSystems.newFileSystem(FileSystems.java:326)
at java.nio.file.FileSystems.newFileSystem(FileSystems.java:276)
at com.company.PageCommandHandler$ProvisioningSteps.getItemModel(PageCommandHandler.java:105)

I've tried creating the zipfile using both OSX's zip utility and using jar cvf but both fail (the output of file <filename> differs slightly however). All the information about this error I can find relates to creating a zipfile using Java NIO, but as you can see I'm only doing a read (verifying the presence of a certain file inside the ZIP for now). Any thoughts on what is going wrong here?

like image 892
Ton van Bart Avatar asked May 24 '16 12:05

Ton van Bart


2 Answers

I've met exactly the same error. Java 8. The reason was, by mistake I created an empty file, not only object:

File zipFile = new File(path);
zipFile.createNewFile();

An then passed this path to

URI uri = URI.create("jar:file:" + zipFile.getAbsolutePath());

To fix it, I did not create file itself, only created a File object:

File zipFile = new File(path);
URI uri = URI.create("jar:file:" + zipFile.getAbsolutePath());

To make it more reliable I would offer to delete file first if it exists:

File zipFile = new File(path);
//Caused by: java.util.zip.ZipError: zip END header not found
if (zipFile.exists()){
    try {
        Files.delete(Paths.get(zipFile.getAbsolutePath()));
    } catch (IOException e) {
        throw new IllegalStateException(
                "Could not delete file.", e);
    }
}
...
URI uri = URI.create("jar:file:" + zipFile.getAbsolutePath());

Probably in some case the solution with deletion of the file is not acceptable. For instance, if you add to the same zip file several entries. But in my use case it is OK.

like image 101
Alexandr Avatar answered Sep 28 '22 07:09

Alexandr


I tried using the normal ZipInputStream and related classes, but kept having issues, so the problem did not seem related to NIO. A colleague of mine found this question on SO: Extracting zipped file from ResourceStream throws error "Invalid stored block lengths"

So I tried adding this snippet to my pom.xml as well:

<properties>
    <project.build.sourceEncoding>ISO-8859-1</project.build.sourceEncoding>
</properties>

After this, all problems disappeared and all my tests turned green. I did not revert back to NIO as I was happy enough getting to a working solution, but I'm pretty sure this would solve the problem on NIO as well.

Posted here in hopes that it helps somebody having the same issue some day.

like image 39
Ton van Bart Avatar answered Sep 28 '22 07:09

Ton van Bart