java - How to unzip all the files in a specific directory of a zip file?
Asked Answered
D

2

5

Say I have a .zip file called Bundles.zip and directly inside Bundles.zip, there are a few files and a few folders. This is what the .zip looks like:

Bundles.zip top level screenshot

Now, I want to extract EVERYTHING from the Bundles folder. My program already knows the name of the folder that it needs to extract the files from, in this case, Bundles.

The Bundles folder inside the zip can have files, subfolders, files in the subfolders, basically anything, like this:

Bundles.zip inner folder screenshot

And I just need to extract everything from the Bundles folder to an output directory.

How can I accomplish this in Java? I have found answers which extract all the files and folders inside the zip, but I need to extract only a specific folder inside the zip, not everything.

Working code so far:

            ZipFile zipFile = new ZipFile(mapsDirectory + "mapUpload.tmp");
            Enumeration zipEntries = zipFile.entries();
            String fname;
            String folderToExtract = "";
            String originalFileNameNoExtension = originalFileName.replace(".zip", "");

            while (zipEntries.hasMoreElements()) {
                ZipEntry ze = ((ZipEntry)zipEntries.nextElement());

                fname = ze.getName();

                if (ze.isDirectory()) //if it is a folder
                {

                    if(originalFileNameNoExtension.contains(fname)) //if this is the folder that I am searching for
                    {
                        folderToExtract = fname; //the name of the folder to extract all the files from is now fname
                        break;
                    }
                }
            }

            if(folderToExtract == "")
            {
                printError(out, "Badly packaged Unturned map error:  " + e.getMessage());
                return;
            }


            //now, how do i extract everything from the folder named folderToExtract?

For the code so far, the originalFileName is something like "The Island.zip". Inside the zip there is a folder called The Island. I need to find the folder inside the zip file that matches the zip file's name, and extract everything inside that.

Debt answered 6/4, 2015 at 20:4 Comment(2)
Where's your working code? The java zip library allows you to iterate through the contents of a zip file just fineOlivarez
@Olivarez - added my working code so far to find the name of the folder to extract. Now the problem is, how do I extract the folder named folderToExtract?Debt
B
0

The path(folder) for the file is part of what "zipEntry.getName()" returns, and should get you the information you need as far as knowing if files are in the folder you seek.

I would do something like:

while (zipEntries.hasMoreElements()) {
  //fname should have the full path
  if (ze.getName().startsWith(fname) && !ze.isDirectory())
    //it is a file within the dir, and it isn't a dir itself
    ...extract files...
  }
}

ZipFile has a getInputStream method to get the input stream for the given ZipEntry, so, something like so:

InputStream instream = zipFile.getInputStream(ze);

Then read the bytes from the stream and write them to a file.

If you need your code to walk 1+ levels deep into sub directories, you can do something like this. Obviously this will not compile, but you get the idea. The method calls itself, and returns to itself making it possible to walk as deep as necessary into sub folders.

private void extractFiles(String folder) {
  //get the files for a given folder
  files = codeThatGetsFilesAndDirs(folder);

  for(file in files) {
    if(file.isDirectory()) {
      extractFiles(file.getName()); 
    } else {
      //code to extract the file and writes it to disk.
    }
  } 
}
Bellwether answered 6/4, 2015 at 21:47 Comment(2)
This worked for getting files in the folder in the zip, but how can i deal with subdirectories inside the folder? The folder in the zip that I want to extract files from also has subdirectories in it, and those subdirectories have files in them too.Debt
You could write a reciprocating method that'll traverse into itself so it can walk the directory tree... that's a bit of a mouthful. I'll post a simple example.Bellwether
A
9

A much easier way to do that is using the NIO API of Java 7. I've just done that for one of my projects:

private void extractSubDir(URI zipFileUri, Path targetDir)
        throws IOException {

    FileSystem zipFs = FileSystems.newFileSystem(zipFileUri, new HashMap<>());
    Path pathInZip = zipFs.getPath("path", "inside", "zip");
    Files.walkFileTree(pathInZip, new SimpleFileVisitor<Path>() {
        @Override
        public FileVisitResult visitFile(Path filePath, BasicFileAttributes attrs) throws IOException {
            // Make sure that we conserve the hierachy of files and folders inside the zip
            Path relativePathInZip = pathInZip.relativize(filePath);
            Path targetPath = targetDir.resolve(relativePathInZip.toString());
            Files.createDirectories(targetPath.getParent());

            // And extract the file
            Files.copy(filePath, targetPath);

            return FileVisitResult.CONTINUE;
        }
    });
}

Voilà. Much cleaner than using ZipFile and ZipEntry, and it has the additional benefit of being re-usable for copying folder structure from ANY type of file system, not only for zip files.

Aldenalder answered 24/5, 2016 at 12:39 Comment(2)
works flawlessly! Don't forget to use "/" as the first parameter to zipFs.getPath() API.Hellgrammite
And if you have a File object and you need a valid zip URI, you can do: URI zipUri = URI.create("jar:file:"+zipFile.getAbsolutePath()) docAtharvaveda
B
0

The path(folder) for the file is part of what "zipEntry.getName()" returns, and should get you the information you need as far as knowing if files are in the folder you seek.

I would do something like:

while (zipEntries.hasMoreElements()) {
  //fname should have the full path
  if (ze.getName().startsWith(fname) && !ze.isDirectory())
    //it is a file within the dir, and it isn't a dir itself
    ...extract files...
  }
}

ZipFile has a getInputStream method to get the input stream for the given ZipEntry, so, something like so:

InputStream instream = zipFile.getInputStream(ze);

Then read the bytes from the stream and write them to a file.

If you need your code to walk 1+ levels deep into sub directories, you can do something like this. Obviously this will not compile, but you get the idea. The method calls itself, and returns to itself making it possible to walk as deep as necessary into sub folders.

private void extractFiles(String folder) {
  //get the files for a given folder
  files = codeThatGetsFilesAndDirs(folder);

  for(file in files) {
    if(file.isDirectory()) {
      extractFiles(file.getName()); 
    } else {
      //code to extract the file and writes it to disk.
    }
  } 
}
Bellwether answered 6/4, 2015 at 21:47 Comment(2)
This worked for getting files in the folder in the zip, but how can i deal with subdirectories inside the folder? The folder in the zip that I want to extract files from also has subdirectories in it, and those subdirectories have files in them too.Debt
You could write a reciprocating method that'll traverse into itself so it can walk the directory tree... that's a bit of a mouthful. I'll post a simple example.Bellwether

© 2022 - 2024 — McMap. All rights reserved.