说明
最近开发有将文件打包成zip文件的需求,以供浏览器直接点击下载。这里可以使用JDK提供的相关方法,也可以使用第三方commons-compress
提供的相关方法,这里需要注意的是以下几点:
- 需要满足可以压缩文件也可以是文件夹的需求。
- 压缩的时候能满足多级目录的需求。
- 空文件夹如需保存需特殊指明,否则空文件夹并不会进行压缩。
- 对于任何一个错误的文件路径,其默认类型为文件夹类型。
JDK方法解压缩
在解压缩文件中,使用到的JDK相关类如下所示:
import java.util.zip.Deflater;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
可以使用java.util.zip
包中的Deflater
类常量可以指定压缩级别,这些常数是如下图所示:
ZipEntry
对象表示Zip
文件格式的归档文件中的条目,ZipInputStream
与ZipOutputStream
是读取zip文件的输入、输出流。下面将演示如何解压缩zip
文件。
- 压缩文件
/**
* 压缩文件
* @param zos 输出流1
* @param file 压缩的文件对象
*/
public static void compressZipFile(ZipOutputStream zos, File file) {
File[] files = file.listFiles();
try {
if (file.isFile()) {
writeZipEntry(zos, file);
} else {
// 空文件夹
if (files.length == 0) {
ZipEntry zipEntry = new ZipEntry(file.getPath() + File.separator);
zos.putNextEntry(zipEntry);
zos.closeEntry();
}
// 递归调用
for (File f : files) {
compressZipFile(zos, f);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 写zip entry对象
* @param zos
* @param f
*/
private static void writeZipEntry(ZipOutputStream zos, File f) {
BufferedInputStream bis = null;
try {
ZipEntry zipEntry = new ZipEntry(f.getPath());
zos.putNextEntry(zipEntry);
bis = new BufferedInputStream(new FileInputStream(f));
int len;
byte[] bytes = new byte[1024];
while ((len = bis.read(bytes)) != -1) {
zos.write(bytes, 0, len);
}
zos.closeEntry();
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
- 解压文件
/**
* 解压文件夹
* @param zis 输入流
* @param path 解压到path路径下
*/
public static void deCompressZipFile(ZipInputStream zis, String path) {
ZipEntry zipEntry = null;
try {
while ((zipEntry = zis.getNextEntry()) != null) {
File file = new File(path + File.separator + zipEntry.getName());
// 如果目录不存在就创建
File parentFile = file.getParentFile();
if (!parentFile.exists()) {
parentFile.mkdirs();
}
if (!zipEntry.isDirectory()) {
// 读取Entry对象
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
byte[] bytes = new byte[1024];
int len;
while ((len = zis.read(bytes)) != -1) {
bos.write(bytes, 0, len);
}
bos.close();
} else {
file.mkdirs();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
测试执行
public static void main(String[] args) throws IOException {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入压缩的文件目录");
String line = scanner.nextLine().trim();
File file = new File(line);
if (!file.exists()) {
System.out.println("输入的路径不合法");
return;
}
File zipFile = new File("test.zip");
ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile)));
zos.setLevel(Deflater.BEST_COMPRESSION);
// 压缩文件
compressZipFile(zos, file);
zos.close();
File f = new File("test.zip");
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(new FileInputStream(f)));
// 解压zip
deCompressZipFile(zis, f.getAbsolutePath().replaceAll(File.separator + f.getName(), ""));
zis.close();
}
commons-compress解压缩
首先引入相关pom依赖如下所示:
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.3</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.18</version>
</dependency>
commons-compress是Apache开源组织提供的用于压缩解压的工具包,其可以支持以下文件格式的文件解压缩,如下图所示:
下面演示如何解压缩。
- 压缩文件
/**
*
* @param srcPath 原文件路径
* @param destFile 压缩文件路径
*/
public static void zipFile(String srcPath, String destFile) {
File outFile = new File(destFile);
FileOutputStream fos = null;
BufferedOutputStream bufferedOutputStream = null;
ArchiveOutputStream out = null;
try {
if (!outFile.exists()) {
outFile.createNewFile();
}
fos = new FileOutputStream(outFile);
bufferedOutputStream = new BufferedOutputStream(fos);
out = new ArchiveStreamFactory().createArchiveOutputStream(
ArchiveStreamFactory.ZIP, bufferedOutputStream);
if (srcPath.charAt(srcPath.length() - 1) != '/') {
srcPath += '/';
}
File f = new File(srcPath);
// 如果是文件夹
if(f.isDirectory()) {
Iterator<File> files = FileUtils.iterateFiles(f,
null, true);
System.out.println(f.getAbsolutePath());
while (files.hasNext()) {
File file = files.next();
writeEntry(srcPath, out, file);
}
} else {
writeEntry(srcPath, out, f);
}
out.finish();
out.close();
bufferedOutputStream.close();
fos.close();
} catch (IOException e) {
e.printStackTrace();
} catch (ArchiveException e) {
e.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
if (bufferedOutputStream != null) {
bufferedOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
private static void writeEntry(String srcPath, ArchiveOutputStream out, File file) throws IOException {
ZipArchiveEntry zipArchiveEntry = new ZipArchiveEntry(file,
file.getPath().replace(srcPath.replace("/", "\\"), ""));
out.putArchiveEntry(zipArchiveEntry);
IOUtils.copy(new FileInputStream(file), out);
out.closeArchiveEntry();
}
- 解压文件
public static void deCompressZip(String zipPath) throws Exception
{
InputStream stream = new FileInputStream(zipPath);
ZipArchiveInputStream inputStream = new ZipArchiveInputStream(stream);
ZipArchiveEntry entry = null;
while ((entry = inputStream.getNextZipEntry()) != null)
{
System.out.println(entry.getName());
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
//读取内容
IOUtils.copy(inputStream, outputStream);
System.out.println(outputStream.toString());
}
inputStream.close();
stream.close();
}