0

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!

joshualan
  • 2,030
  • 8
  • 23
  • 32
  • The error actually doesn't happen in the code, it happens when I try to read from the file. I'm updating the post for more info. – joshualan Aug 13 '12 at 19:24
  • Dup of http://stackoverflow.com/questions/1399126/java-util-zip-recreating-directory-structure – mazaneicha Aug 13 '12 at 19:24
  • @joshualan If you are seeing a `NullPointerException`, we need to know which line is triggering it. If it's not in the code listed above then where is it being thrown? – Duncan Jones Aug 13 '12 at 19:26
  • I added the code where it throws the error, it's at the conditional statement in the while loop. – joshualan Aug 13 '12 at 19:34
  • @mazaneicha I am thinking it might not be a duplicate, that one is trying to create a zip archive while I'm trying to extract one from a zip archive. If I am wrong, how does that question solve my problem? – joshualan Aug 13 '12 at 19:39
  • With the code as written, you cannot get NullPointerException on the readLine call. I suspect extractedFile is null. Can you print it out to confirm? Otherwise, it is the newFileReader method. Or is that a call to new FileReader? – John Watts Aug 13 '12 at 21:34

3 Answers3

1

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.

mazaneicha
  • 8,794
  • 4
  • 33
  • 52
  • Yeah, I think this is the problem too, I'm new to Java so I thought that my problem was actually the way I was writing to the file, not the path to the file. O_O – joshualan Aug 13 '12 at 21:30
1
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.

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Thanks, I actually thought the way I was writing to the file was wrong. I made the code write to a static file (for a temporary fix) and it seems it works! – joshualan Aug 13 '12 at 21:31
0

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.

John Watts
  • 8,717
  • 1
  • 31
  • 35
  • I edited the code to only iterate using using iteration 2 but still the same error so I guess the two different iterations isn't it. – joshualan Aug 13 '12 at 19:33
  • Then I would go with the other answers. The parent directory of the unzipped file does not exist and your error handling code turns this into a NullPointerException. A stack trace and an indication of the line numbers in the above code sure would help. – John Watts Aug 13 '12 at 21:25