ZipCompressor.java是一个常见的压缩工具类,使用java的内置算法,可以用于压缩文件和文件夹。
这个工具类很简单,我们来看一下它的实现。
首先我们来看构造函数
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.zip.CRC32;
import java.util.zip.CheckedOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
* zip压缩工具<br>
* 含有中文请谨慎,zip文件在不同操作系统容易中文乱码.
*
*/
public class ZipCompressor {
static final int BUFFER = 8192;
private File zipFile;
/**
* 压缩器构造函数
*
* @param pathName 压缩包路径<br>
* e.g /Users/Admin/Desktop/test.zip
*/
public ZipCompressor(String pathName) {
zipFile = new File(pathName);
if (zipFile.exists()) {
System.out.println("删除旧的压缩文件:" + pathName);
zipFile.delete();
}
}
}
在构造函数中,我们获取pathName的文件对象,pathName就是压缩文件路径,如果这个文件存在,也就是有以前压缩的数据,我们先删除它
接下来是提供外部调用的压缩方法
/**
* 压缩一个文件,或者一个文件夹
*
* @param srcPathName 文件路径,或文件夹路径
*/
public void compress(String srcPathName) {
File file = new File(srcPathName);
if (!file.exists())
throw new RuntimeException(srcPathName + "不存在!");
try {
FileOutputStream fileOutputStream = new FileOutputStream(zipFile);
CheckedOutputStream cos = new CheckedOutputStream(fileOutputStream,
new CRC32());
ZipOutputStream out = new ZipOutputStream(cos);
String basedir = "";
compress(file, out, basedir);
out.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 压缩多个文件
*
* @param filePaths 文件路径
*/
public void compress(String[] filePaths) {
try {
FileOutputStream fileOutputStream = new FileOutputStream(zipFile);
CheckedOutputStream cos = new CheckedOutputStream(fileOutputStream,
new CRC32());
ZipOutputStream out = new ZipOutputStream(cos);
String basedir = "";
for (int i = 0; i < filePaths.length; i++) {
compress(new File(filePaths[i]), out, basedir);
}
out.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
上面有两个方法,分别用于压缩文件和文件夹,但是其实没有真正的压缩实现
首先是获得要压缩文件的输出流,将它封装成CheckedOutputStream,目的是为了指定文件校验算法。(通常使用CRC32算法)。
然后封装成ZipOutputStream流
调用compress()方法进行压缩
private void compress(File file, ZipOutputStream out, String basedir) {
/* 判断是目录还是文件 */
if (file.isDirectory()) {
System.out.println("压缩:" + basedir + file.getName());
this.compressDirectory(file, out, basedir);
} else {
System.out.println("压缩:" + basedir + file.getName());
this.compressFile(file, out, basedir);
}
}
对于文件和文件夹,分别调用不同的方法
/** 压缩一个目录 */
private void compressDirectory(File dir, ZipOutputStream out, String basedir) {
if (!dir.exists())
return;
File[] files = dir.listFiles();
for (int i = 0; i < files.length; i++) {
/* 递归 */
compress(files[i], out, basedir + dir.getName() + "/");
}
}
/** 压缩一个文件 */
private void compressFile(File file, ZipOutputStream out, String basedir) {
if (!file.exists())
return;
try {
BufferedInputStream bis = new BufferedInputStream(
new FileInputStream(file));
ZipEntry entry = new ZipEntry(basedir + file.getName());
out.putNextEntry(entry);
int count;
byte data[] = new byte[BUFFER];
while ((count = bis.read(data, 0, BUFFER)) != -1) {
out.write(data, 0, count);
}
bis.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
对于文件夹compressDirectory()方法中逐个去递归调用compress()方法,每次还要传入上级文件夹路径
只有是文件才进行真正的压缩
在compressFile()方法里面
获得要压缩文件的输入流
分装一个ZipEntry对象,ZipEntry就是压缩包中的每一个实体
这种设计条目对象的思想在文件处理中经常用到
然后提供一个缓冲池
使用ZipOutputStream的write()方法进行文件写入即可
完整代码:
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.zip.CRC32;
import java.util.zip.CheckedOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
* zip压缩工具<br>
* 含有中文请谨慎,zip文件在不同操作系统容易中文乱码.
*
*/
public class ZipCompressor {
static final int BUFFER = 8192;
private File zipFile;
/**
* 压缩器构造函数
*
* @param pathName 压缩包路径<br>
* e.g /Users/Admin/Desktop/test.zip
*/
public ZipCompressor(String pathName) {
zipFile = new File(pathName);
if (zipFile.exists()) {
System.out.println("删除旧的压缩文件:" + pathName);
zipFile.delete();
}
}
/**
* 压缩一个文件,或者一个文件夹
*
* @param srcPathName 文件路径,或文件夹路径
*/
public void compress(String srcPathName) {
File file = new File(srcPathName);
if (!file.exists())
throw new RuntimeException(srcPathName + "不存在!");
try {
FileOutputStream fileOutputStream = new FileOutputStream(zipFile);
CheckedOutputStream cos = new CheckedOutputStream(fileOutputStream,
new CRC32());
ZipOutputStream out = new ZipOutputStream(cos);
String basedir = "";
compress(file, out, basedir);
out.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 压缩多个文件
*
* @param filePaths 文件路径
*/
public void compress(String[] filePaths) {
try {
FileOutputStream fileOutputStream = new FileOutputStream(zipFile);
CheckedOutputStream cos = new CheckedOutputStream(fileOutputStream,
new CRC32());
ZipOutputStream out = new ZipOutputStream(cos);
String basedir = "";
for (int i = 0; i < filePaths.length; i++) {
compress(new File(filePaths[i]), out, basedir);
}
out.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private void compress(File file, ZipOutputStream out, String basedir) {
/* 判断是目录还是文件 */
if (file.isDirectory()) {
System.out.println("压缩:" + basedir + file.getName());
this.compressDirectory(file, out, basedir);
} else {
System.out.println("压缩:" + basedir + file.getName());
this.compressFile(file, out, basedir);
}
}
/** 压缩一个目录 */
private void compressDirectory(File dir, ZipOutputStream out, String basedir) {
if (!dir.exists())
return;
File[] files = dir.listFiles();
for (int i = 0; i < files.length; i++) {
/* 递归 */
compress(files[i], out, basedir + dir.getName() + "/");
}
}
/** 压缩一个文件 */
private void compressFile(File file, ZipOutputStream out, String basedir) {
if (!file.exists())
return;
try {
BufferedInputStream bis = new BufferedInputStream(
new FileInputStream(file));
ZipEntry entry = new ZipEntry(basedir + file.getName());
out.putNextEntry(entry);
int count;
byte data[] = new byte[BUFFER];
while ((count = bis.read(data, 0, BUFFER)) != -1) {
out.write(data, 0, count);
}
bis.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}