package io.zip;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.Enumeration;
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipFile;
import org.apache.tools.zip.ZipOutputStream;
/**
*
* @author zhangyu 用zip压缩和解压缩文件或目录
*/
public class CompressUtil {
/**
* 压缩文件或是目录
*
* @param baseDirName
* 压缩文件的根目录
* @param fileName
* 根目录下待压缩的文件或文件夹名 星号*表示压缩根目录下的全部文件
* @param targetFileName
* 目标zip文件
*/
public static void zipFile(String baseDirName, String fileName,
String targetFileName) {
if (null == baseDirName) {
System.out.println("压缩失败,跟目录不存在:" + baseDirName);
return;
}
File baseDir = new File(baseDirName);
if (!baseDir.exists() || (!baseDir.isDirectory())) {
System.out.println("压缩失败,跟目录不存在:" + baseDir);
return;
}
String baseDirPath = baseDir.getAbsolutePath();
// 目标文件
File targetFile = new File(targetFileName);
// 创建一个zip输出流来压缩数据并写入到zip文件
try {
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(
targetFile));
out.setEncoding("GBK");
if ("*".equals(fileName)) {
// 将baseDir目录下的所有文件压缩到ZIP
CompressUtil.dirToZip(baseDirPath, baseDir, out);
} else {
File file = new File(baseDir, fileName);
if (file.isFile()) {
CompressUtil.fileToZip(baseDirPath, file, out);
} else {
CompressUtil.dirToZip(baseDirPath, file, out);
}
}
out.close();
System.out.println("压缩文件成功,目标文件名:" + targetFileName);
} catch (IOException e) {
System.out.println("压缩失败: " + e);
e.printStackTrace();
}
}
/**
* 解压缩ZIP文件 将ZIP文件里的内容解压到targetBaseDirName目录下
*
* @param zipFileName
* 待解压缩的ZIP文件名
* @param targetBaseDirName
* 目标目录
*/
public static void upzipFile(String zipFileName, String targetBaseDirName) {
if (!targetBaseDirName.endsWith(File.separator)) {
targetBaseDirName += File.separator;
}
try {
// 根据ZIP文件创建ZipFile对象
ZipFile zipFile = new ZipFile(zipFileName);
ZipEntry entry = null;
String entryName = null;
String targetFileName = null;
byte[] buffer = new byte[4096];
int bytes_red;
// 获取ZIP文件里所有的entry
Enumeration entrys = zipFile.getEntries();
// 遍历多有entry
while (entrys.hasMoreElements()) {
entry = (ZipEntry) entrys.nextElement();
// 获得entry的名字
entryName = entry.getName();
targetFileName = targetBaseDirName + entryName;
if (entry.isDirectory()) {
// 如果entry是一个目录,则创建目录
new File(targetFileName).mkdirs();
} else {
// 如果entry是一个文件,则创建父目录
new File(targetFileName).getParentFile().mkdirs();
}
// 是否创建文件
File targetFile = new File(targetFileName);
System.out.println("创建文件:" + targetFile.getAbsolutePath());
// 打开文件输出流
FileOutputStream os = new FileOutputStream(targetFile);
// 从ZipFile对象中打开entry的输入流
InputStream is = zipFile.getInputStream(entry);
while ((bytes_red = is.read(buffer)) != -1) {
os.write(buffer, 0, bytes_red);
}
// 关闭流
os.close();
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
/** 将目录压缩到ZIP输出流 */
private static void dirToZip(String baseDirPath, File dir,
ZipOutputStream out) {
if (dir.isDirectory()) {
// 列出dir目录下所有文件
File[] files = dir.listFiles();
// 如果是空文件夹
if (files.length == 0) {
ZipEntry entry = new ZipEntry(getEntryName(baseDirPath, dir));
// 存储目录信息
try {
out.putNextEntry(entry);
out.closeEntry();
} catch (IOException e) {
e.printStackTrace();
}
return;
}
for (int i = 0; i < files.length; i++) {
if (files[i].isFile()) {
// 如果是文件,调用fileToZip方法
CompressUtil.fileToZip(baseDirPath, files[i], out);
} else {
// 如果是目录,递归调用
CompressUtil.dirToZip(baseDirPath, files[i], out);
}
}
}
}
/** 将文件压缩到ZIP输出流 */
private static void fileToZip(String baseDirPath, File file,
ZipOutputStream out) {
FileInputStream in = null;
ZipEntry entry = null;
// 创建复制缓冲区
byte[] buffer = new byte[4096];
int bytes_red;
String filePath = file.getAbsolutePath();
try {
file = new File(changeCharset(filePath));
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
}
if (file.isFile()) {
try {
in = new FileInputStream(file);// 创建一个文件输入流
// 构造一个ZipEntry
entry = new ZipEntry(getEntryName(baseDirPath, file));
out.putNextEntry(entry);// 存储项信息到压缩文件
// 复制字节到压缩文件
while ((bytes_red = in.read(buffer)) != -1) {
out.write(buffer, 0, bytes_red);
}
out.closeEntry();
in.close();
System.out.println("添加文件" + file.getAbsolutePath()
+ "被添加到ZIP文件中!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
/** 获取待压缩文件在ZIP文件中entry的名字,即相对于跟目录的相对路径名 */
private static String getEntryName(String baseDirPath, File file) {
if (!baseDirPath.endsWith(File.pathSeparator)) {
baseDirPath += File.separator;
}
String filePath = file.getAbsolutePath();
// 对于目录,必须在entry名字后面加上"/"表示它将以目录项存储
if (file.isDirectory()) {
filePath += "/";
}
int index = filePath.indexOf(baseDirPath);
return filePath.substring(index + baseDirPath.length());
}
public static void main(String[] args) {
// 压缩d盘下的ceshi目录,压缩后的文件是d:/ceshi.zip
String baseDirName = "D:/";
String fileName = "ceshi";
String zipFileName = "D:/ceshi.zip";
CompressUtil.zipFile(baseDirName, fileName, zipFileName);
// 将刚创建的ZIP文件解压缩到D盘的测试目录下
System.out.println();
fileName = "D:/ceshiZip";
File file = new File(fileName);
if (file.exists()) {
file.delete();
}
CompressUtil.upzipFile(zipFileName, fileName);
}
/**
* 转换成utf-8编码格式
*
* @throws UnsupportedEncodingException
*/
private static String changeCharset(String str)
throws UnsupportedEncodingException {
if (null != str) {
// 用默认字符编码解码字符串。与系统有关,中文windows默认是GB2312
byte[] bs = str.getBytes();
return new String(bs, "UTF_8");
}
return null;
}
}