如何在Android中以编程方式解压缩文件?

问题

我需要一个小代码片段,它从给定的.zip文件中解压缩一些文件,并根据它们在压缩文件中的格式提供单独的文件。请发布你的知识并帮助我。


#1 热门回答(127 赞)

如果peno的版本有所优化。性能的提高是可感知的。

private boolean unpackZip(String path, String zipname)
{       
     InputStream is;
     ZipInputStream zis;
     try 
     {
         String filename;
         is = new FileInputStream(path + zipname);
         zis = new ZipInputStream(new BufferedInputStream(is));          
         ZipEntry ze;
         byte[] buffer = new byte[1024];
         int count;

         while ((ze = zis.getNextEntry()) != null) 
         {
             // zapis do souboru
             filename = ze.getName();

             // Need to create directories if not exists, or
             // it will generate an Exception...
             if (ze.isDirectory()) {
                File fmd = new File(path + filename);
                fmd.mkdirs();
                continue;
             }

             FileOutputStream fout = new FileOutputStream(path + filename);

             // cteni zipu a zapis
             while ((count = zis.read(buffer)) != -1) 
             {
                 fout.write(buffer, 0, count);             
             }

             fout.close();               
             zis.closeEntry();
         }

         zis.close();
     } 
     catch(IOException e)
     {
         e.printStackTrace();
         return false;
     }

    return true;
}

#2 热门回答(79 赞)

基于瓦西里·索辛斯基的答案有点调整和一个小修复:

public static void unzip(File zipFile, File targetDirectory) throws IOException {
    ZipInputStream zis = new ZipInputStream(
            new BufferedInputStream(new FileInputStream(zipFile)));
    try {
        ZipEntry ze;
        int count;
        byte[] buffer = new byte[8192];
        while ((ze = zis.getNextEntry()) != null) {
            File file = new File(targetDirectory, ze.getName());
            File dir = ze.isDirectory() ? file : file.getParentFile();
            if (!dir.isDirectory() && !dir.mkdirs())
                throw new FileNotFoundException("Failed to ensure directory: " +
                        dir.getAbsolutePath());
            if (ze.isDirectory())
                continue;
            FileOutputStream fout = new FileOutputStream(file);
            try {
                while ((count = zis.read(buffer)) != -1)
                    fout.write(buffer, 0, count);
            } finally {
                fout.close();
            }
            /* if time should be restored as well
            long time = ze.getTime();
            if (time > 0)
                file.setLastModified(time);
            */
        }
    } finally {
        zis.close();
    }
}

显着差异

  • public static - 这是一个静态的实用方法,可以在任何地方。
  • 2个文件参数,因为String是:/对于文件,一个无法指定之前提取zip文件的位置。路径文件名连接> https://stackoverflow.com/a/412495/995891
  • 抛出 - 因为迟到 - 添加一个尝试捕获,如果真的不感兴趣。
  • 实际上确保所有情况下都存在所需的目录。并非每个zip都包含文件条目之前的所有必需目录条目。这有两个潜在的错误:如果zip包含一个空目录,而不是生成的目录有一个现有的文件,这被忽略了。 mkdirs()的返回值很重要。可能会崩溃不包含目录的zip文件。
  • 增加写缓冲区大小,这应该会提高性能。存储通常是4k块,以较小的块写入通常比必要的慢。
  • 利用最终的魔力来防止资源泄漏。

所以

unzip(new File("/sdcard/pictures.zip"), new File("/sdcard"));

应该做相当于原件

unpackZip("/sdcard/", "pictures.zip")

#3 热门回答(21 赞)

这是我的解压缩方法,我用它:

private boolean unpackZip(String path, String zipname)
{       
     InputStream is;
     ZipInputStream zis;
     try 
     {
         is = new FileInputStream(path + zipname);
         zis = new ZipInputStream(new BufferedInputStream(is));          
         ZipEntry ze;

         while((ze = zis.getNextEntry()) != null) 
         {
             ByteArrayOutputStream baos = new ByteArrayOutputStream();
             byte[] buffer = new byte[1024];
             int count;

             String filename = ze.getName();
             FileOutputStream fout = new FileOutputStream(path + filename);

             // reading and writing
             while((count = zis.read(buffer)) != -1) 
             {
                 baos.write(buffer, 0, count);
                 byte[] bytes = baos.toByteArray();
                 fout.write(bytes);             
                 baos.reset();
             }

             fout.close();               
             zis.closeEntry();
         }

         zis.close();
     } 
     catch(IOException e)
     {
         e.printStackTrace();
         return false;
     }

    return true;
}