第一步叔收,導(dǎo)入maven依賴
<!-- StopWatch耗時計算 -->
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
第二步齿穗,創(chuàng)建并編寫ZipUtils類,運(yùn)行main方法查看效果饺律,如下
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.time.StopWatch;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
* 說明:
* (1)可以壓縮文件窃页,也可以壓縮文件夾
* (2)同時支持壓縮多級文件夾,工具內(nèi)部做了遞歸處理
* (3)碰到空的文件夾,也可以壓縮
* (4)可以選擇是否保留原來的目錄結(jié)構(gòu)脖卖,如果不保留乒省,所有文件跑壓縮包根目錄去了,且空文件夾直接舍棄畦木。注意:如果不保留文件原來目錄結(jié)構(gòu)袖扛,在碰到文件名相同的文件時,會壓縮失敗十籍。
* (5)代碼中提供了2個壓縮文件的方法蛆封,一個的輸入?yún)?shù)為文件夾路徑,一個為文件列表勾栗,可根據(jù)實際需求選擇方法惨篱。
* 注意:
* (1)支持選擇是否保留原來的文件目錄結(jié)構(gòu),如果不保留围俘,那么空文件夾直接不用處理砸讳。
* (2)碰到空文件夾時,如果需要保留目錄結(jié)構(gòu)楷拳,則直接添加個ZipEntry就可以了绣夺,不過就是這個entry的名字后面需要帶上一斜杠(/)表示這個是目錄吏奸。
* (3)遞歸時欢揖,不需要把zip輸出流關(guān)閉,zip輸出流的關(guān)閉應(yīng)該是在調(diào)用完遞歸方法后面關(guān)閉
* (4)遞歸時奋蔚,如果是個文件夾且需要保留目錄結(jié)構(gòu)她混,那么在調(diào)用方法壓縮他的子文件時,需要把文件夾的名字加一斜杠給添加到子文件名字前面泊碑,這樣壓縮后才有多級目錄坤按。
* @author jhx
* @date 2021年2月121日 下午7:16:08
* @version v1.0
*/
@Slf4j
public class ZipUtils {
private static final int BUFFER_SIZE = 2 * 1024;
public static void main(String[] args) throws Exception {
log.info("測試開始!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
// 1
// 壓縮后的文件
FileOutputStream fileOutputStream1 = new FileOutputStream("/Users/luoyu/Downloads/test.zip");
ZipUtils.toZip("/Users/luoyu/Downloads/日報內(nèi)容.txt", fileOutputStream1,true);
// 2
List<File> fileList = new ArrayList<>();
fileList.add(new File("/Users/luoyu/Downloads/日報內(nèi)容1.txt"));
fileList.add(new File("/Users/luoyu/Downloads/日報內(nèi)容2.txt"));
FileOutputStream fileOutputStream2 = new FileOutputStream("/Users/luoyu/Downloads/test.zip");
ZipUtils.toZip(fileList, fileOutputStream2);
log.info("測試結(jié)束!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
}
/**
* 單個
* @param srcDir 要壓縮文件路徑
* @param out 壓縮后文件輸出流
* @param KeepDirStructure 是否保留原來的目錄結(jié)構(gòu),true:保留目錄結(jié)構(gòu);
* false:所有文件跑到壓縮包根目錄下(注意:不保留目錄結(jié)構(gòu)可能會出現(xiàn)同名文件,會壓縮失敗)
*/
public static void toZip(String srcDir, OutputStream out, boolean KeepDirStructure)
throws Exception{
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ZipOutputStream zos = null ;
try {
zos = new ZipOutputStream(out);
File sourceFile = new File(srcDir);
compress(sourceFile, zos, sourceFile.getName(), KeepDirStructure);
stopWatch.stop();
log.info("壓縮完成,耗時:{}馒过。", (double) stopWatch.getTime()/1000 + "s");
} catch (Exception e) {
throw new Exception("壓縮失敵襞А:" + e);
}finally{
if(zos != null){
try {
zos.close();
} catch (Exception e) {
log.error("壓縮失敗:" + e);
}
}
}
}
/**
* 多個
* @param srcFiles 需要壓縮的文件列表
* @param out 壓縮后文件輸出流
*/
public static void toZip(List<File> srcFiles , OutputStream out)throws Exception {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ZipOutputStream zos = null ;
try {
zos = new ZipOutputStream(out);
for (File srcFile : srcFiles) {
byte[] buf = new byte[BUFFER_SIZE];
zos.putNextEntry(new ZipEntry(srcFile.getName()));
int len;
FileInputStream in = new FileInputStream(srcFile);
while ((len = in.read(buf)) != -1){
zos.write(buf, 0, len);
}
zos.closeEntry();
in.close();
}
stopWatch.stop();
log.info("壓縮完成腹忽,耗時:{}来累。", (double) stopWatch.getTime()/1000 + "s");
} catch (Exception e) {
throw new Exception("壓縮失敗:" + e);
}finally{
if(zos != null){
try {
zos.close();
} catch (Exception e) {
log.error("壓縮失斁阶唷:" + e);
}
}
}
}
/**
* 遞歸壓縮方法
* @param sourceFile 源文件
* @param zos zip輸出流
* @param name 壓縮后的名稱
* @param KeepDirStructure 是否保留原來的目錄結(jié)構(gòu),true:保留目錄結(jié)構(gòu);
* false:所有文件跑到壓縮包根目錄下(注意:不保留目錄結(jié)構(gòu)可能會出現(xiàn)同名文件,會壓縮失敗)
*/
private static void compress(File sourceFile, ZipOutputStream zos, String name,
boolean KeepDirStructure) throws Exception{
byte[] buf = new byte[BUFFER_SIZE];
if(sourceFile.isFile()){
// 向zip輸出流中添加一個zip實體嘹锁,構(gòu)造器中name為zip實體的文件的名字
zos.putNextEntry(new ZipEntry(name));
// copy文件到zip輸出流中
int len;
FileInputStream in = new FileInputStream(sourceFile);
while ((len = in.read(buf)) != -1){
zos.write(buf, 0, len);
}
// Complete the entry
zos.closeEntry();
in.close();
} else {
File[] listFiles = sourceFile.listFiles();
if(listFiles == null || listFiles.length == 0){
// 需要保留原來的文件結(jié)構(gòu)時,需要對空文件夾進(jìn)行處理
if(KeepDirStructure){
// 空文件夾的處理
zos.putNextEntry(new ZipEntry(name + "/"));
// 沒有文件,不需要文件的copy
zos.closeEntry();
}
}else {
for (File file : listFiles) {
// 判斷是否需要保留原來的文件結(jié)構(gòu)
if (KeepDirStructure) {
// 注意:file.getName()前面需要帶上父文件夾的名字加一斜杠,
// 不然最后壓縮包中就不能保留原來的文件結(jié)構(gòu),即:所有文件都跑到壓縮包根目錄下了
compress(file, zos, name + "/" + file.getName(),KeepDirStructure);
} else {
compress(file, zos, file.getName(),KeepDirStructure);
}
}
}
}
}
}
注:此工程包含多個包着裹,本文所用代碼均在com.luoyu.java.zip包下
最后編輯于 :
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者