我应该如何提取java中的压缩文件夹?

发布于 2024-07-23 03:20:18 字数 2026 浏览 1 评论 0原文

我正在使用以下代码在 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语句,这不会提取文件夹树。 我尝试使用递归来处理文件夹树,但失败了。 有人可以告诉我如何改进此代码以处理文件夹树而不是压缩的单级文件夹。

I am using the following code to extract a zip file in Java.

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

}

Obviously this will not extract a folder tree because of the break statement. I tried to use recursion to process a folder tree but failed. Could someone show me how to improve this code to handle a folder tree instead of a compressed single level folder.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

冷情 2024-07-30 03:20:18

您可以使用 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();
    }
}

You can use File.mkdirs() to create folders. Try changing your method like this:

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();
    }
}
倾其所爱 2024-07-30 03:20:18

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

Another option is commons-compress, for which there is sample code on the site linked above.

挥剑断情 2024-07-30 03:20:18

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

我发现@Emre 的答案不能正常工作。 由于某种原因,ZipEntry 跳过了 JAR 中的一些文件(没有明显的模式)。 我通过使用 JarEntry 解决了这个问题。 上面的代码中还有一个错误,即可以在目录之前枚举 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;
}

I needed to do this because of an API which I was using required a File parameter, which you can't get from a resource in a JAR.

I found that the answer from @Emre didn't work correctly. For some reason ZipEntry skipped a few files in the JAR (no apparent pattern to this). I fixed this by using JarEntry instead. There is also a bug in the above code where the file in the zip entry could be enumerated before the directory is, which causes an exception because the directory hasn't been created yet.

Note that the below code depends on Apache Commons utility classes.

/**
 * 
 * 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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文