如何解压缩zip文件中特定目录下的所有文件?

5

假设我有一个名为Bundles.zip的 .zip 文件,直接在Bundles.zip里面,有一些文件和一些文件夹。这是 .zip 文件的样子:

Bundles.zip top level screenshot

现在,我想从“Bundles”文件夹中提取 EVERYTHING 。我的程序已经知道它需要从哪个文件夹中提取文件的名称,在这种情况下是 Bundles 。
压缩文件中的 Bundles 文件夹可以包含文件、子文件夹、子文件夹中的文件,基本上可以包含任何东西,如下所示:

Bundles.zip inner folder screenshot

我只需要将Bundles文件夹中的所有内容提取到输出目录中。

我该如何在Java中实现这一点?我已经找到了提取zip文件中所有文件和文件夹的答案,但我需要仅提取zip文件中的特定文件夹,而不是全部内容。

到目前为止,工作代码如下:

            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?

到目前为止的代码中,originalFileName 是类似于 "The Island.zip" 的东西。在 zip 文件中有一个名为 The Island 的文件夹。我需要找到与 zip 文件名匹配的 zip 文件内部的文件夹,并提取其中的所有内容。

你的工作代码在哪里?Java zip库可以很好地遍历zip文件的内容。 - kolossus
@kolossus - 我已经添加了我的工作代码,以查找要提取的文件夹的名称。现在的问题是,如何提取名为folderToExtract的文件夹? - user3149729
2个回答

9

使用Java 7的NIO API是更加简便的方法。我刚刚为我的一个项目完成了这个操作:

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;
        }
    });
}

看,比使用ZipFileZipEntry要简洁得多,并且它具有额外的好处,可以重复使用,用于从任何类型的文件系统复制文件夹结构,而不仅仅是针对zip文件。


完美运行!不要忘记在zipFs.getPath() API的第一个参数中使用“/”。 - Gaurav
如果您有一个文件对象并且需要一个有效的zip URI,可以执行以下操作:URI zipUri = URI.create("jar:file:"+zipFile.getAbsolutePath())文档 - Bruno Bossola

0

文件的路径(文件夹)是“zipEntry.getName()”返回的一部分,应该可以为您提供所需的信息,以便知道文件是否在您要查找的文件夹中。

我会这样做:

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有一个getInputStream方法,用于获取给定ZipEntry的输入流,因此可以像这样:

InputStream instream = zipFile.getInputStream(ze);

然后从流中读取字节并将它们写入文件。

如果您需要让代码深入子目录超过1个级别,可以像这样做。显然,这不会编译,但您可以理解这个想法。该方法调用自身,并返回给自身,使得可以深入到子文件夹中。

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.
    }
  } 
}

这适用于获取压缩文件夹中的文件,但是如何处理文件夹内部的子目录?我想要从zip文件中提取文件的文件夹也有其中的子目录,并且那些子目录里面也有文件。 - user3149729
你可以编写一个递归方法,它会遍历自身,以便能够遍历目录树... 这有点啰嗦。我将发布一个简单的示例。 - slambeth

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接