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