【问题标题】:How should I extract compressed folders in java?我应该如何在java中提取压缩文件夹?
【发布时间】:2010-10-30 15:38:14
【问题描述】:

我正在使用以下代码在 Java 中提取一个 zip 文件。

import java.io.*;
import java.util.zip.*;

class  testZipFiles 
{
    public static void main(String[] args) 
    {

        try
        {
            String filename = "C:\\zip\\includes.zip";
            testZipFiles list = new testZipFiles( );
            list.getZipFiles(filename);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    public void getZipFiles(String filename)
    {
        try
        {
            String destinationname = "c:\\zip\\";
            byte[] buf = new byte[1024];
            ZipInputStream zipinputstream = null;
            ZipEntry zipentry;
            zipinputstream = new ZipInputStream(
            new FileInputStream(filename));

            zipentry = zipinputstream.getNextEntry();
            while (zipentry != null) 
            { 
                //for each entry to be extracted
                String entryName = zipentry.getName();
                System.out.println("entryname "+entryName);
                int n;
                FileOutputStream fileoutputstream;
                File newFile = new File(entryName);
                String directory = newFile.getParent();

                if(directory == null)
                {
                    if(newFile.isDirectory())
                    break;
                }

                fileoutputstream = new FileOutputStream(
                   destinationname+entryName);             

                while ((n = zipinputstream.read(buf, 0, 1024)) > -1)
                    fileoutputstream.write(buf, 0, n);

                fileoutputstream.close(); 
                zipinputstream.closeEntry();
                zipentry = zipinputstream.getNextEntry();

            }//while

            zipinputstream.close();
        }
        catch (Exception e)
       {
            e.printStackTrace();
       }
  }

}

显然,由于 break 语句,这不会提取文件夹树。我尝试使用递归来处理文件夹树但失败了。有人可以告诉我如何改进此代码以处理文件夹树而不是压缩的单级文件夹。

【问题讨论】:

  • Chathuranga:Emre 的回答是否解决了您的问题?如果是这样,请检查他的答案来感谢他=)

标签: java compression zip extraction


【解决方案1】:

您可以使用 File.mkdirs() 创建文件夹。尝试像这样更改您的方法:

public static void getZipFiles(String filename) {
    try {
        String destinationname = "c:\\zip\\";
        byte[] buf = new byte[1024];
        ZipInputStream zipinputstream = null;
        ZipEntry zipentry;
        zipinputstream = new ZipInputStream(
                new FileInputStream(filename));

        zipentry = zipinputstream.getNextEntry();
        while (zipentry != null) {
            //for each entry to be extracted
            String entryName = destinationname + zipentry.getName();
            entryName = entryName.replace('/', File.separatorChar);
            entryName = entryName.replace('\\', File.separatorChar);
            System.out.println("entryname " + entryName);
            int n;
            FileOutputStream fileoutputstream;
            File newFile = new File(entryName);
            if (zipentry.isDirectory()) {
                if (!newFile.mkdirs()) {
                    break;
                }
                zipentry = zipinputstream.getNextEntry();
                continue;
            }

            fileoutputstream = new FileOutputStream(entryName);

            while ((n = zipinputstream.read(buf, 0, 1024)) > -1) {
                fileoutputstream.write(buf, 0, n);
            }

            fileoutputstream.close();
            zipinputstream.closeEntry();
            zipentry = zipinputstream.getNextEntry();

        }//while

        zipinputstream.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

【讨论】:

  • ZipEntry 有一个名为 isDirectory() 的方法。这应该可以简化 zip 存档中目录条目的检测。
  • 你可能是对的。在 isDirectory() 的 javadoc 中,它说“目录条目被定义为名称以 '/' 结尾的条目”。我编辑了我的答案。
【解决方案2】:

另一个选项是commons-compress,上面链接的网站上有示例代码。

【讨论】:

    【解决方案3】:

    我需要这样做,因为我使用的 API 需要一个文件参数,而您无法从 JAR 中的资源中获取该参数。

    我发现@Emre 的答案没有正常工作。出于某种原因,ZipEntry 跳过了 JAR 中的一些文件(对此没有明显的模式)。我改用 JarEntry 解决了这个问题。上面的代码还有一个bug,就是zip入口中的文件可能在目录之前就被枚举出来了,导致这个目录还没有被创建,导致异常。

    请注意,以下代码依赖于 Apache Commons 实用程序类。

    /**
     * 
     * Extract a directory in a JAR on the classpath to an output folder.
     * 
     * Note: User's responsibility to ensure that the files are actually in a JAR.
     * The way that I do this is to get the URI with
     *     URI url = getClass().getResource("/myresource").toURI();
     * and then if url.isOpaque() we are in a JAR. There may be a more reliable
     * way however, please edit this answer if you know of one.
     * 
     * @param classInJar A class in the JAR file which is on the classpath
     * @param resourceDirectory Path to resource directory in JAR
     * @param outputDirectory Directory to write to  
     * @return String containing the path to the folder in the outputDirectory
     * @throws IOException
     */
    private static String extractDirectoryFromClasspathJAR(Class<?> classInJar, String resourceDirectory, String outputDirectory)
            throws IOException {
    
        resourceDirectory = StringUtils.strip(resourceDirectory, "\\/") + File.separator;
    
        URL jar = classInJar.getProtectionDomain().getCodeSource().getLocation();
        //Note: If you want to extract from a named JAR, remove the above 
        //line and replace "jar.getFile()" below with the path to the JAR.
        JarFile jarFile = new JarFile(new File(jar.getFile()));
    
        byte[] buf = new byte[1024];
        Enumeration<JarEntry> jarEntries = jarFile.entries();
        while (jarEntries.hasMoreElements()) {
            JarEntry jarEntry = jarEntries.nextElement();
    
            if (jarEntry.isDirectory() || !jarEntry.getName().startsWith(resourceDirectory)) {
                continue;               
            }
    
    
            String outputFileName = FilenameUtils.concat(outputDirectory, jarEntry.getName());
            //Create directories if they don't exist
            new File(FilenameUtils.getFullPath(outputFileName)).mkdirs();
    
            //Write file
            FileOutputStream fileOutputStream = new FileOutputStream(outputFileName);
            int n;
            InputStream is = jarFile.getInputStream(jarEntry);
            while ((n = is.read(buf, 0, 1024)) > -1) {
                fileOutputStream.write(buf, 0, n);
            }
            is.close();
            fileOutputStream.close();
        }
        jarFile.close();
    
        String fullPath = FilenameUtils.concat(outputDirectory, resourceDirectory);
        return fullPath;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-10
      • 1970-01-01
      • 1970-01-01
      • 2022-07-27
      • 1970-01-01
      • 1970-01-01
      • 2012-01-23
      • 1970-01-01
      相关资源
      最近更新 更多