简体   繁体   中英

Error on Extracting a File in zip archive in Java

I'm extracting a file from a zip archive using this code (omitting all the catch statements and other initialization statements):

zipInputStream = new ZipInputStream(new FileInputStream(file));
zipFile = new ZipFile(file);
for (Enumeration<?> em = zipFile.entries(); em.hasMoreElements();) {
    String extractedFileName = em.nextElement().toString();
    ZipEntry outerZipEntry = zipInputStream.getNextEntry();
    if (outerZipEntry.getName().contains(searchString)) {
        extractedFile = new File(outputDir + outerZipEntry.getName());
        out = new FileOutputStream(outputDir + extractedFileName);
        byte[] buf = new byte[1024];
        int len;
        while ((len = zipInputStream.read(buf)) > 0) {
            out.write(buf, 0, len);
        }
        break;
     } 
}

This code works fine when extracting a file in say, /archive.zip/file_i_need.txt.

But when I'm trying to extract a file from /archive.zip/folder1/file_i_need.txt, I get an exception java.lang.NullPointerException when I try to use readLine() to read the file in:

String line = null ;
BufferedReader input = new BufferedReader(newFileReader(extractedFile)) ;
while( (line = input.readLine() ) != null ) {
    ...
}

I've tested it on both cases and it seems like this code will not work when the file is inside a folder because the extractedFileName is 'folder/file_i_need.txt' compared to just 'file_i_need.txt'.

Any suggestions you can recommend?

Thanks!

I think your issue is that you can't open a FileOutputStream on line out = new FileOutputStream(outputDir + extractedFileName); . You can't open a stream because if extractedFileName is folder1/file_i_need.txt and outputDir is, for example, C:/OutputDir then you're trying to open a stream on C:/OutputDirfolder1/file_i_need.txt . Such directory doesn't exist and out becomes null. The post I was referring to in my comment does have a unzip operation, and ther you can see the special handling of directory entries in a zip file.

extractedFile = new File(outputDir + outerZipEntry.getName());

The problem is you're not taking into account that the entries name may contain a path element, which you are not creating, you simply try an write to the file. Why this doesn't produce an error, I'm not sure.

Are you writing these files on Windows?? This would create a file like folder1/file_i_need.txt on the file system, which is probably invalid at some level :P

Try extracting the file name from the ZipEntry

String name = outerZipEntry.getName();
name = name.substring(name.lastIndexOf("/") + 1);

Obviously, check that name actually contains a "/" first ;)

UPDATE

While I'm at it, this looks wrong

extractedFile = new File(outputDir + outerZipEntry.getName());
out = new FileOutputStream(outputDir + extractedFileName);

Basically your saying outputDir + outerZipEntry.getName() + (outputDir + outerZipEntry.getName())

UPDATE

I tested this on Windows and I get a FileNotFoundException when I try and write the file to a path that does not exist

I also tested it on my MaC and I get a FileNotFoundException

I don't know what your error handling is doing, but it's doing it wrong.

You are iterating over zip entries in two different ways:

Iteration 1:

for (Enumeration<?> em = zipFile.entries(); em.hasMoreElements();) {

Iteration 2:

ZipEntry outerZipEntry = zipInputStream.getNextEntry();

Just do one or the other. Either use the ZipFile API or the ZipInputStream API. I strongly suspect that is where the NullPointerException is coming from.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM