项目开发中需要用到文件压缩的功能,结合网上资料,自己整理了几种压缩方法,具体的时间性能方面的比较在自己电脑上测试的结果没有太大差距,后续再进行详细测试分析下。因为是要实现从服务器下载文件夹类型的功能,所以对于文件压缩率采取了最低压缩率的方式(基本和源文件大小一样,只是把文件夹转成了zip的压缩文件方便能够下载),如果对于压缩率有要求的可以在zipOut.setLevel(0);这条语句中更改0为其他数值(可取值0-9,从0到9压缩率越高,生成的压缩文件越小但是所耗时间越长)。
public static void compress(String source, String destinct)
throws IOException, InterruptedException {
List<File> fileList = loadFilename(new File(source));
if(fileList.size()<=0){
throw new IOException("文件路径下不存在文件");
}
/******压缩方法二(Channel)-BEGIN******/
/*File zipFile = new File(destinct);
try (ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFile));
WritableByteChannel writableByteChannel = Channels.newChannel(zipOut)) {
zipOut.setLevel(0);
for (int i = 0; i < fileList.size(); i++) {
File file = (File) fileList.get(i);
String entryName = getEntryName(source, file);
String filePath = file.getPath();
if(file.isDirectory()){//添加压缩空文件夹
entryName = entryName+"/";
filePath = filePath+"/";
zipOut.putNextEntry(new ZipEntry(entryName));
continue;
}
try (FileChannel fileChannel = new FileInputStream(filePath).getChannel()) {
zipOut.putNextEntry(new ZipEntry(entryName));
fileChannel.transferTo(0, fileChannel.size(), writableByteChannel);
}
}
} catch (Exception e) {
e.printStackTrace();
}*/
/******压缩方法二-END******/
/******压缩方法一(Buffered传输) BEGIN******/
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(
new File(destinct)));
zos.setLevel(0);//采用最快等级压缩,压缩文件大小最大
byte[] buffere = new byte[8192];
int length;
BufferedInputStream bis;
for (int i = 0; i < fileList.size(); i++) {
File file = (File) fileList.get(i);
String entryName = getEntryName(source, file);
if(file.isDirectory()){//添加压缩空文件夹
entryName = entryName+"/";
zos.putNextEntry(new ZipEntry(entryName));
zos.closeEntry();
continue;
}
zos.putNextEntry(new ZipEntry(entryName));
bis = new BufferedInputStream(new FileInputStream(file));
while ((length=bis.read(buffere))!=-1) {
zos.write(buffere, 0, length);
}
bis.close();
zos.closeEntry();
}
zos.close();
/******压缩方法一 END******/
/******压缩方法三(ZipArchiveOutputStream) BEGIN******/
/*if (fileList != null && fileList.size() > 0) {
ZipArchiveOutputStream zaos = null;
try {
zaos = new ZipArchiveOutputStream(new File(destinct));
zaos.setLevel(0);//采用最快等级压缩,压缩文件大小最大
// Use Zip64 extensions for all entries where they are required
zaos.setUseZip64(Zip64Mode.AsNeeded);
// 将每个文件用ZipArchiveEntry封装
// 再用ZipArchiveOutputStream写到压缩文件中
for (File file : fileList) {
if (file != null) {
String entryName = getEntryName(source, file);
ZipArchiveEntry zipArchiveEntry = new ZipArchiveEntry(file, entryName);
zaos.putArchiveEntry(zipArchiveEntry);
if(file.isDirectory()){//添加压缩空文件夹
zaos.closeArchiveEntry();
continue;
}
InputStream is = null;
try {
is = new FileInputStream(file);
byte[] buffer = new byte[1024 * 5];
int len = -1;
while ((len = is.read(buffer)) != -1) {
// 把缓冲区的字节写入到ZipArchiveEntry
zaos.write(buffer, 0, len);
}
zaos.closeArchiveEntry();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (is != null)
is.close();
}
}
}
zaos.finish();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (zaos != null) {
zaos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}*/
/******压缩方法三 END*******/
}
/**
* 递归获得该文件下所有文件名(不包括目录名)
*
* @param file
* @return
*/
private static List<File> loadFilename(File file) {
List<File> filenameList = new ArrayList<>();
if (file.isFile()) {
filenameList.add(file);
}
if (file.isDirectory()) {
if(file.listFiles().length<=0){//添加空文件夹
filenameList.add(file);
}
for (File f : file.listFiles()) {
filenameList.addAll(loadFilename(f));
}
}
return filenameList;
}
/**
* 获得zip entry 字符串
*
* @param base
* @param file
* @return
*/
private static String getEntryName(String base, File file) {
File baseFile = new File(base);
String filename = file.getPath();
// int index=filename.lastIndexOf(baseFile.getName());
if (baseFile.getParentFile().getParentFile() == null){
return filename.substring(baseFile.getParent().length());
}
return filename.substring(baseFile.getParent().length() + 1);
}