35

我有 zip 文件,其中包含一些其他 zip 文件。

例如,邮件文件是abc.zip,它包含xyz.zip, class1.java, class2.java. 并xyz.zip包含文件class3.javaclass4.java.

因此,我需要使用 Java 将 zip 文件解压缩到应包含class1.javaclass2.java和.class3.javaclass4.java

4

9 回答 9

85

警告,这里的代码对于受信任的 zip 文件是可以的,在写入之前没有路径验证,如果您使用它来压缩来自未知客户端的上传 zip 文件,可能会导致安全漏洞,如zip-slip-vulnerability中所述。


此解决方案与之前已发布的解决方案非常相似,但此解决方案在解压缩时重新创建了正确的文件夹结构。

public static void extractFolder(String zipFile) throws IOException {
int buffer = 2048;
File file = new File(zipFile);

try (ZipFile zip = new ZipFile(file)) {
  String newPath = zipFile.substring(0, zipFile.length() - 4);

  new File(newPath).mkdir();
  Enumeration<? extends ZipEntry> zipFileEntries = zip.entries();

  // Process each entry
  while (zipFileEntries.hasMoreElements()) {
    // grab a zip file entry
    ZipEntry entry = zipFileEntries.nextElement();
    String currentEntry = entry.getName();
    File destFile = new File(newPath, currentEntry);
    File destinationParent = destFile.getParentFile();

    // create the parent directory structure if needed
    destinationParent.mkdirs();

    if (!entry.isDirectory()) {
      BufferedInputStream is = new BufferedInputStream(zip.getInputStream(entry));
      int currentByte;
      // establish buffer for writing file
      byte[] data = new byte[buffer];

      // write the current file to disk
      FileOutputStream fos = new FileOutputStream(destFile);
      try (BufferedOutputStream dest = new BufferedOutputStream(fos, buffer)) {

        // read and write until last byte is encountered
        while ((currentByte = is.read(data, 0, buffer)) != -1) {
          dest.write(data, 0, currentByte);
        }
        dest.flush();
        is.close();
      }
    }

    if (currentEntry.endsWith(".zip")) {
      // found a zip file, try to open
      extractFolder(destFile.getAbsolutePath());
    }
  }
}

}

于 2011-08-18T14:12:57.970 回答
9

这是一些未经测试的代码库,基于我解压缩文件的一些旧代码。

public void doUnzip(String inputZip, String destinationDirectory)
        throws IOException {
    int BUFFER = 2048;
    List zipFiles = new ArrayList();
    File sourceZipFile = new File(inputZip);
    File unzipDestinationDirectory = new File(destinationDirectory);
    unzipDestinationDirectory.mkdir();

    ZipFile zipFile;
    // Open Zip file for reading
    zipFile = new ZipFile(sourceZipFile, ZipFile.OPEN_READ);

    // Create an enumeration of the entries in the zip file
    Enumeration zipFileEntries = zipFile.entries();

    // Process each entry
    while (zipFileEntries.hasMoreElements()) {
        // grab a zip file entry
        ZipEntry entry = (ZipEntry) zipFileEntries.nextElement();

        String currentEntry = entry.getName();

        File destFile = new File(unzipDestinationDirectory, currentEntry);
        destFile = new File(unzipDestinationDirectory, destFile.getName());

        if (currentEntry.endsWith(".zip")) {
            zipFiles.add(destFile.getAbsolutePath());
        }

        // grab file's parent directory structure
        File destinationParent = destFile.getParentFile();

        // create the parent directory structure if needed
        destinationParent.mkdirs();

        try {
            // extract file if not a directory
            if (!entry.isDirectory()) {
                BufferedInputStream is =
                        new BufferedInputStream(zipFile.getInputStream(entry));
                int currentByte;
                // establish buffer for writing file
                byte data[] = new byte[BUFFER];

                // write the current file to disk
                FileOutputStream fos = new FileOutputStream(destFile);
                BufferedOutputStream dest =
                        new BufferedOutputStream(fos, BUFFER);

                // read and write until last byte is encountered
                while ((currentByte = is.read(data, 0, BUFFER)) != -1) {
                    dest.write(data, 0, currentByte);
                }
                dest.flush();
                dest.close();
                is.close();
            }
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }
    zipFile.close();

    for (Iterator iter = zipFiles.iterator(); iter.hasNext();) {
        String zipName = (String)iter.next();
        doUnzip(
            zipName,
            destinationDirectory +
                File.separatorChar +
                zipName.substring(0,zipName.lastIndexOf(".zip"))
        );
    }

}
于 2009-06-11T15:14:55.193 回答
7

我拿 ca.anderson4 并删除 List zipFiles 并重写一点,这就是我得到的:

public class Unzip {

public void unzip(String zipFile) throws ZipException,
        IOException {

    System.out.println(zipFile);;
    int BUFFER = 2048;
    File file = new File(zipFile);

    ZipFile zip = new ZipFile(file);
    String newPath = zipFile.substring(0, zipFile.length() - 4);

    new File(newPath).mkdir();
    Enumeration zipFileEntries = zip.entries();

    // Process each entry
    while (zipFileEntries.hasMoreElements()) {
        // grab a zip file entry
        ZipEntry entry = (ZipEntry) zipFileEntries.nextElement();

        String currentEntry = entry.getName();

        File destFile = new File(newPath, currentEntry);
        destFile = new File(newPath, destFile.getName());
        File destinationParent = destFile.getParentFile();

        // create the parent directory structure if needed
        destinationParent.mkdirs();
        if (!entry.isDirectory()) {
            BufferedInputStream is = new BufferedInputStream(zip
                    .getInputStream(entry));
            int currentByte;
            // establish buffer for writing file
            byte data[] = new byte[BUFFER];

            // write the current file to disk
            FileOutputStream fos = new FileOutputStream(destFile);
            BufferedOutputStream dest = new BufferedOutputStream(fos,
                    BUFFER);

            // read and write until last byte is encountered
            while ((currentByte = is.read(data, 0, BUFFER)) != -1) {
                dest.write(data, 0, currentByte);
            }
            dest.flush();
            dest.close();
            is.close();
        }
        if (currentEntry.endsWith(".zip")) {
            // found a zip file, try to open
            unzip(destFile.getAbsolutePath());
        }
    }
}

public static void main(String[] args) {
    Unzip unzipper=new Unzip();
    try {
        unzipper.unzip("test/test.zip");
    } catch (ZipException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

}

我测试过并且有效

于 2009-06-12T22:03:59.210 回答
2

In testing I noticed File.mkDirs() does not work under Windows...

/** * for a given full path name recreate all parent directories **/

    private void createParentHierarchy(String parentName) throws IOException {
        File parent = new File(parentName);
        String[] parentsStrArr = parent.getAbsolutePath().split(File.separator == "/" ? "/" : "\\\\");

        //create the parents of the parent
        for(int i=0; i < parentsStrArr.length; i++){
            StringBuffer currParentPath = new StringBuffer();
            for(int j = 0; j < i; j++){
                currParentPath.append(parentsStrArr[j]+File.separator);
            }
            File currParent = new File(currParentPath.toString());
            if(!currParent.isDirectory()){
                boolean created = currParent.mkdir();
                if(isVerbose)log("creating directory "+currParent.getAbsolutePath());
            }
        }

        //create the parent itself
        if(!parent.isDirectory()){
            boolean success = parent.mkdir();
        }
    }
于 2009-06-13T14:38:32.110 回答
2

根据需要进行修改,然后混合一些最佳答案。该版本将:

  • 递归提取 zip 到给定位置

  • 创建空目录

  • 正确关闭拉链


public static void unZipAll(File source, File destination) throws IOException 
{
    System.out.println("Unzipping - " + source.getName());
    int BUFFER = 2048;

    ZipFile zip = new ZipFile(source);
    try{
        destination.getParentFile().mkdirs();
        Enumeration zipFileEntries = zip.entries();

        // Process each entry
        while (zipFileEntries.hasMoreElements())
        {
            // grab a zip file entry
            ZipEntry entry = (ZipEntry) zipFileEntries.nextElement();
            String currentEntry = entry.getName();
            File destFile = new File(destination, currentEntry);
            //destFile = new File(newPath, destFile.getName());
            File destinationParent = destFile.getParentFile();

            // create the parent directory structure if needed
            destinationParent.mkdirs();

            if (!entry.isDirectory())
            {
                BufferedInputStream is = null;
                FileOutputStream fos = null;
                BufferedOutputStream dest = null;
                try{
                    is = new BufferedInputStream(zip.getInputStream(entry));
                    int currentByte;
                    // establish buffer for writing file
                    byte data[] = new byte[BUFFER];

                    // write the current file to disk
                    fos = new FileOutputStream(destFile);
                    dest = new BufferedOutputStream(fos, BUFFER);

                    // read and write until last byte is encountered
                    while ((currentByte = is.read(data, 0, BUFFER)) != -1) {
                        dest.write(data, 0, currentByte);
                    }
                } catch (Exception e){
                    System.out.println("unable to extract entry:" + entry.getName());
                    throw e;
                } finally{
                    if (dest != null){
                        dest.close();
                    }
                    if (fos != null){
                        fos.close();
                    }
                    if (is != null){
                        is.close();
                    }
                }
            }else{
                //Create directory
                destFile.mkdirs();
            }

            if (currentEntry.endsWith(".zip"))
            {
                // found a zip file, try to extract
                unZipAll(destFile, destinationParent);
                if(!destFile.delete()){
                    System.out.println("Could not delete zip");
                }
            }
        }
    } catch(Exception e){
        e.printStackTrace();
        System.out.println("Failed to successfully unzip:" + source.getName());
    } finally {
        zip.close();
    }
    System.out.println("Done Unzipping:" + source.getName());
}
于 2014-07-08T21:44:28.413 回答
1

解压缩后应关闭 zip 文件。

static public void extractFolder(String zipFile) throws ZipException, IOException 
{
    System.out.println(zipFile);
    int BUFFER = 2048;
    File file = new File(zipFile);

    ZipFile zip = new ZipFile(file);
    try
    { 
       ...code from other answers ( ex. NeilMonday )...
    }
    finally
    {
        zip.close();
    }
}
于 2012-05-03T14:19:51.340 回答
0

与 NeilMonday 的回答相同,但提取空目录:

static public void extractFolder(String zipFile) throws ZipException, IOException 
{
    System.out.println(zipFile);
    int BUFFER = 2048;
    File file = new File(zipFile);

    ZipFile zip = new ZipFile(file);
    String newPath = zipFile.substring(0, zipFile.length() - 4);

    new File(newPath).mkdir();
    Enumeration zipFileEntries = zip.entries();

    // Process each entry
    while (zipFileEntries.hasMoreElements())
    {
        // grab a zip file entry
        ZipEntry entry = (ZipEntry) zipFileEntries.nextElement();
        String currentEntry = entry.getName();
        File destFile = new File(newPath, currentEntry);
        //destFile = new File(newPath, destFile.getName());
        File destinationParent = destFile.getParentFile();

        // create the parent directory structure if needed
        destinationParent.mkdirs();

        if (!entry.isDirectory())
        {
            BufferedInputStream is = new BufferedInputStream(zip
            .getInputStream(entry));
            int currentByte;
            // establish buffer for writing file
            byte data[] = new byte[BUFFER];

            // write the current file to disk
            FileOutputStream fos = new FileOutputStream(destFile);
            BufferedOutputStream dest = new BufferedOutputStream(fos,
            BUFFER);

            // read and write until last byte is encountered
            while ((currentByte = is.read(data, 0, BUFFER)) != -1) {
                dest.write(data, 0, currentByte);
            }
            dest.flush();
            dest.close();
            is.close();
        }
        else{
            destFile.mkdirs()
        }
        if (currentEntry.endsWith(".zip"))
        {
            // found a zip file, try to open
            extractFolder(destFile.getAbsolutePath());
        }
    }
}
于 2012-02-29T19:30:53.770 回答
0

这是一些代码,我测试它运行良好:

package com.test;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

public class Unzipper {  
    private final static int BUFFER_SIZE = 2048;
    private final static String ZIP_FILE = "/home/anton/test/test.zip";
    private final static String DESTINATION_DIRECTORY = "/home/anton/test/";
    private final static String ZIP_EXTENSION = ".zip";
 
    public static void main(String[] args) {
     System.out.println("Trying to unzip file " + ZIP_FILE); 
        Unzipper unzip = new Unzipper();  
        if (unzip.unzipToFile(ZIP_FILE, DESTINATION_DIRECTORY)) {
         System.out.println("Succefully unzipped to the directory " 
             + DESTINATION_DIRECTORY);
        } else {
         System.out.println("There was some error during extracting archive to the directory " 
             + DESTINATION_DIRECTORY);
        }
    } 

 public boolean unzipToFile(String srcZipFileName,
   String destDirectoryName) {
  try {
   BufferedInputStream bufIS = null;
   // create the destination directory structure (if needed)
   File destDirectory = new File(destDirectoryName);
   destDirectory.mkdirs();

   // open archive for reading
   File file = new File(srcZipFileName);
   ZipFile zipFile = new ZipFile(file, ZipFile.OPEN_READ);

   //for every zip archive entry do
   Enumeration<? extends ZipEntry> zipFileEntries = zipFile.entries();
   while (zipFileEntries.hasMoreElements()) {
    ZipEntry entry = (ZipEntry) zipFileEntries.nextElement();
    System.out.println("\tExtracting entry: " + entry);

    //create destination file
    File destFile = new File(destDirectory, entry.getName());

    //create parent directories if needed
    File parentDestFile = destFile.getParentFile();    
    parentDestFile.mkdirs();    
    
    if (!entry.isDirectory()) {
     bufIS = new BufferedInputStream(
       zipFile.getInputStream(entry));
     int currentByte;

     // buffer for writing file
     byte data[] = new byte[BUFFER_SIZE];

     // write the current file to disk
     FileOutputStream fOS = new FileOutputStream(destFile);
     BufferedOutputStream bufOS = new BufferedOutputStream(fOS, BUFFER_SIZE);

     while ((currentByte = bufIS.read(data, 0, BUFFER_SIZE)) != -1) {
      bufOS.write(data, 0, currentByte);
     }

     // close BufferedOutputStream
     bufOS.flush();
     bufOS.close();

     // recursively unzip files
     if (entry.getName().toLowerCase().endsWith(ZIP_EXTENSION)) {
      String zipFilePath = destDirectory.getPath() + File.separatorChar + entry.getName();

      unzipToFile(zipFilePath, zipFilePath.substring(0, 
              zipFilePath.length() - ZIP_EXTENSION.length()));
     }
    }
   }
   bufIS.close();
   return true;
  } catch (Exception e) {
   e.printStackTrace();
   return false;
  }
 } 
}  

我在这里尝试了最高投票的答案,它不会递归解压缩文件,它只是解压缩第一级的文件。

来源:将文件提取到给定目录的解决方案

另外,由同一个人检查此解决方案:在内存中提取文件的解决方案

于 2020-07-08T04:01:56.393 回答
-3
File dir = new File("BASE DIRECTORY PATH");
FileFilter ff = new FileFilter() {

    @Override
    public boolean accept(File f) {
        //only want zip files
        return (f.isFile() && f.getName().toLowerCase().endsWith(".zip"));
    }
};

File[] list = null;
while ((list = dir.listFiles(ff)).length > 0) {
    File file1 = list[0];
    //TODO unzip the file to the base directory
}
于 2009-06-11T15:06:34.027 回答