以下是一个使用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); } } }