一、起因
开发中需要实现文件的压缩及解压功能,以满足某些特定场景的下的需要,在此说下具体实现。
二、实现
1.定义一个工具类ZipUtils,实现文件的压缩及解压,代码如下:
import java.io.*;
import java.nio.charset.Charset;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
/**
* ZIP解压缩工具
*/
public class ZipUtils {
/**
* 压缩文件/文件夹
* 若压缩的为文件夹:则压缩包中第一层为该文件夹
* 若压缩的为文件:则压缩包中第一层为该文件
*
* @param srcFilePath 源文件
* @param zipFilePath zip
*/
public static void compress(String srcFilePath, String zipFilePath) {
File src = new File(srcFilePath);
if (!src.exists()) {
throw new RuntimeException(srcFilePath + "不存在");
}
File zipFile = new File(zipFilePath);
try (ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile)))) {
String baseDir = "";
compress(src, zos, baseDir);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 压缩
*
* @param src
* @param zos
* @param baseDir
*/
public static void compress(File src, ZipOutputStream zos, String baseDir) {
if (!src.exists())
return;
if (src.isFile()) {
compressFile(src, zos, baseDir);
} else if (src.isDirectory()) {
compressDir(src, zos, baseDir);
}
}
/**
* 压缩文件
*/
private static void compressFile(File file, ZipOutputStream zos, String baseDir) {
if (!file.exists())
return;
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file))) {
ZipEntry entry = new ZipEntry(baseDir + file.getName());
zos.putNextEntry(entry);
int count;
byte[] buf = new byte[4096];
while ((count = bis.read(buf)) != -1) {
zos.write(buf, 0, count);
}
} catch (Exception e) {
}
}
/**
* 压缩文件夹
*/
private static void compressDir(File dir, ZipOutputStream zos, String baseDir) {
if (!dir.exists() || dir.isFile())
return;
File[] files = dir.listFiles();
if (files != null) {
if (files.length == 0) {
try {
zos.putNextEntry(new ZipEntry(baseDir + dir.getName() + File.separator));
} catch (IOException e) {
e.printStackTrace();
}
} else {
for (File file : files) {
compress(file, zos, baseDir + dir.getName() + File.separator);
}
}
}
}
/**
* 解压文件
*
* @param zipFilePath
* @param destDirPath
*/
public static void unzip(String zipFilePath, String destDirPath) {
File srcFile = new File(zipFilePath);
unzip(srcFile, destDirPath);
}
/**
* 解压文件
*
* @param srcFile
* @param destDirPath
*/
public static void unzip(File srcFile, String destDirPath) {
if (!srcFile.exists()) {
throw new RuntimeException(srcFile.getPath() + "所指文件不存在");
} else if (!srcFile.isFile()) {
throw new RuntimeException(srcFile.getPath() + "所指文件为文件夹");
}
try (ZipFile zipFile = new ZipFile(srcFile, Charset.forName("GBK"))) {
Enumeration<?> entries = zipFile.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = (ZipEntry) entries.nextElement();
if (entry.isDirectory()) {
String dirPath = destDirPath + File.separator + entry.getName();
File dir = new File(dirPath);
dir.mkdirs();
} else {
File targetFile = new File(destDirPath + File.separator + entry.getName());
if (!targetFile.getParentFile().exists()) {
targetFile.getParentFile().mkdirs();
}
targetFile.createNewFile();
InputStream is = zipFile.getInputStream(entry);
FileOutputStream fos = new FileOutputStream(targetFile);
int len;
byte[] buf = new byte[4096];
while ((len = is.read(buf)) != -1) {
fos.write(buf, 0, len);
}
fos.close();
is.close();
}
}
} catch (Exception e) {
throw new RuntimeException("unzip error from ZipUtils", e);
}
}
}
2.压缩和解压示例
提前在D盘根目录下新建一个文件夹,命名为1;在文件夹1里面再新建一个文件夹,命名为2;在文件夹2里面新建一个txt文档,名称任意,内容任意。最终文件结构为:
将下述调用代码与上述代码放于同一项目中,执行下述代码后,文件结构将变成
其中2.zip是压缩后的结果;文件夹3下的内容是解压2.zip后的结果。
public class Demo {
public static void main(String[] args) {
ZipUtils.compress("D:\\1\\2", "D:\\1\\2.zip");
ZipUtils.unzip("D:\\1\\2.zip", "D:\\1\\3");
}
}