使用Java解压缩包含子目录的压缩文件

后端 潘老师 6个月前 (10-23) 135 ℃ (0) 扫码查看

以下是一个使用java.util.zip包解压缩和提取压缩zip文件中的文件的Java代码示例。

该示例打开一个zip文件,并以与遍历目录树类似的方式遍历文件。如果我们找到一个目录条目,我们将创建一个新目录。如果我们找到一个文件条目,我们将写入解压缩的文件。

1.使用java.util.zip.ZipFile解压缩文件

该示例使用ZipInputStream读取ZipFile,然后逐个读取ZipEntry。然后使用FileOutputStream将所有文件写入文件系统。

以下示例执行以下操作:

  • 创建一个新文件夹,将解压缩的文件复制到该文件夹中。文件夹名称取自zip文件名,但不包括扩展名。例如,如果我们解压缩data.zip文件,则将其提取到同一位置的data文件夹中。ZipFile对象表示.zip文件,用于访问其信息。
  • 程序遍历zip中的所有文件,检查它是目录还是文件。ZipEntry类代表zip文件中的一个条目,可以是文件或目录。每个ZipEntry实例都有压缩和解压缩大小信息,名称以及未压缩字节的输入流。
  • 如果ZipEntry是目录,则在目标目录中创建新目录;否则将文件解压缩到该位置。
  • 使用Files.copy(),我们读取zip中的未压缩文件并将其复制到目标路径。
  • 一直这样做,直到整个文件被处理完。
import java.io.*;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.apache.commons.io.FilenameUtils;
public class UnzipExample
{
  public static void main(String[] args)
  {
    Path zipFile = Path.of("c:/temp/data.zip");
    unzipFile(zipFile);
  }
  private static void unzipFile(Path filePathToUnzip) {
    Path parentDir = filePathToUnzip.getParent();
    String fileName = filePathToUnzip.toFile().getName();
    Path targetDir = parentDir.resolve(FilenameUtils.removeExtension(fileName));
    //Open the file
    try (ZipFile zip = new ZipFile(filePathToUnzip.toFile())) {
      FileSystem fileSystem = FileSystems.getDefault();
      Enumeration<? extends ZipEntry> entries = zip.entries();
      //We will unzip files in this folder
      if (!targetDir.toFile().isDirectory()
          && !targetDir.toFile().mkdirs()) {
        throw new IOException("failed to create directory " + targetDir);
      }
      //Iterate over entries
      while (entries.hasMoreElements()) {
        ZipEntry entry = entries.nextElement();
        File f = new File(targetDir.resolve(Path.of(entry.getName())).toString());
        //If directory then create a new directory in uncompressed folder
        if (entry.isDirectory()) {
          if (!f.isDirectory() && !f.mkdirs()) {
            throw new IOException("failed to create directory " + f);
          }
        }
        //Else create the file
        else {
          File parent = f.getParentFile();
          if (!parent.isDirectory() && !parent.mkdirs()) {
            throw new IOException("failed to create directory " + parent);
          }
          try(InputStream in = zip.getInputStream(entry)) {
            Files.copy(in, f.toPath());
          }
        }
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

2. 使用Apache Commons Compress解压缩文件

使用commons-compress库解压缩文件的总体步骤与第一部分所述的步骤类似。只有类名不同,其他只有很少的差异。

从maven仓库导入commons-compress的最新版本。

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-compress</artifactId>
    <version>1.21</version>
</dependency>

好的,让我们开始使用压缩API重写这个逻辑。主要的改变是引入了新的类:ArchiveEntry、ArchiveStreamFactory和ArchiveInputStream。

  • ArchiveEntry实例提供了关于各个压缩文件条目的元数据。
  • ArchiveInputStream有助于读取各种格式的压缩文件,如.zip、.zip.gz或.tar.gz文件。例如,要读取tar文件,我们可以按以下方式创建一个TarArchiveInputStream实例。
try (InputStream fi = Files.newInputStream(Paths.get("my.tar.gz"));
     InputStream bi = new BufferedInputStream(fi);
     InputStream gzi = new GzipCompressorInputStream(bi);
     ArchiveInputStream o = new TarArchiveInputStream(gzi)) {
}

让我们创建一个简单的程序,类似于第一个示例,它将把给定的压缩文件解压到同一目录中。

import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.ArchiveException;
import org.apache.commons.compress.archivers.ArchiveInputStream;
import org.apache.commons.compress.archivers.ArchiveStreamFactory;
import org.apache.commons.compress.utils.IOUtils;
import org.apache.commons.io.FilenameUtils;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class UnzipWithCommonCompress {
  public static void main(String[] args) throws IOException, ArchiveException {
    Path zipFile = Path.of("c:/temp/data.zip");
    extractZip(zipFile);
  }
  private static void extractZip(Path zipFilePath) {
    Path parentDir = zipFilePath.getParent();
    String fileName = zipFilePath.toFile().getName();
    Path targetDir = parentDir.resolve(FilenameUtils.removeExtension(fileName));
    ArchiveStreamFactory archiveStreamFactory = new ArchiveStreamFactory();
    try (InputStream inputStream = Files.newInputStream(zipFilePath);
         ArchiveInputStream archiveInputStream = archiveStreamFactory
             .createArchiveInputStream(ArchiveStreamFactory.ZIP, inputStream)) {
      ArchiveEntry archiveEntry = null;
      while ((archiveEntry = archiveInputStream.getNextEntry()) != null) {
        Path path = Paths.get(targetDir.toString(), archiveEntry.getName());
        File file = path.toFile();
        if (archiveEntry.isDirectory()) {
          if (!file.isDirectory()) {
            file.mkdirs();
          }
        } else {
          File parent = file.getParentFile();
          if (!parent.isDirectory()) {
            parent.mkdirs();
          }
          try (OutputStream outputStream = Files.newOutputStream(path)) {
            IOUtils.copy(archiveInputStream, outputStream);
          }
        }
      }
    } catch (IOException e) {
      throw new RuntimeException(e);
    } catch (ArchiveException e) {
      throw new RuntimeException(e);
    }
  }
}

 


版权声明:本站文章,如无说明,均为本站原创,转载请注明文章来源。如有侵权,请联系博主删除。
本文链接:https://www.panziye.com/back/10252.html
喜欢 (0)
请潘老师喝杯Coffee吧!】
分享 (0)
用户头像
发表我的评论
取消评论
表情 贴图 签到 代码

Hi,您需要填写昵称和邮箱!

  • 昵称【必填】
  • 邮箱【必填】
  • 网址【可选】