Как я должен извлечь сжатые папки в Java? - PullRequest
8 голосов
/ 02 июня 2009

Я использую следующий код для извлечения zip-файла в 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();
       }
  }

}

Очевидно, что это не будет извлекать дерево папок из-за оператора break. Я попытался использовать рекурсию для обработки дерева папок, но не получилось. Может кто-нибудь показать мне, как улучшить этот код для обработки дерева папок вместо сжатой одноуровневой папки.

Ответы [ 3 ]

7 голосов
/ 02 июня 2009

Вы можете использовать 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();
    }
}
0 голосов
/ 21 мая 2013

Мне нужно было сделать это, потому что 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;
}
0 голосов
/ 28 ноября 2012

Другой вариант - commons-compress , для которого на сайте, указанном выше, есть пример кода.

...