解壓一個目錄包括子目錄中的所有 zip 檔案
阿新 • • 發佈:2021-01-10
解壓一個目錄包括子目錄中的所有 zip 檔案
package unzip;
import java.io.*;
import java.nio.charset.Charset;
import java.util.*;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
/**
* @author jeffrey
* @ClassName: UnZip
* @Description: 為偷懶而生,解壓一個目錄包括子目錄中的所有 zip 檔案
* @date: 2021/1/9 12:38 上午
* @version:
* @since JDK 1.8
*/
public class UnZip {
/**
* 用於存放於 zip 檔案的安全佇列
*/
public final static ConcurrentLinkedQueue<File> ZIP_QUEUE = new ConcurrentLinkedQueue<>();
/**
* 如 t1 不存活並 zipQueue 為空則修改為 true
*/
public static boolean isFlag = false;
/**
* 輸入流
*/
private static final Scanner SCANNER = new Scanner(System.in);
/**
* 提供一個工作路徑
*/
private static String workPath;
/**
* 在解壓完成後是否刪除原始檔
* 使用 Boolean 包裝類進行判斷,True / true 為 true,False / false 為 false,其他依然為 false
*/
public static String isDelete;
/**
* 在解壓檔案時發生異常的集合
* Key:檔名
* Value:異常物件
*/
public static final HashMap<File, Exception> unZipFailedMap = new HashMap<>();
/**
* 找到相關的檔案數量
*/
public static int foundCount = 0;
/**
* 成功解壓的檔案數量
*/
public static int succeedCount = 0;
/**
* 解壓失敗的檔案數量
*/
public static int unZipFailedCount = 0;
/**
* 刪除失敗的檔案個數
*/
public static int deleteFailedCount = 0;
/**
* 刪除失敗的檔名
*/
public static final HashSet<File> deleteFailedNameList = new HashSet<>();
public static void main(String[] args) {
input();
if (new File(workPath).exists()) {
Thread t1 = new Thread(new FindZipFile(new File(workPath)));
Thread t2 = new Thread(new UnZipFile(ZIP_QUEUE));
t1.start();
t2.start();
while (true) {
if (!t1.isAlive() && ZIP_QUEUE.isEmpty()) {
isFlag = true;
if (!t2.isAlive()) {
System.out.println
(
"\n\n\n" +
"共找到了 " + foundCount + " 個檔案\n" +
"成功解壓了 " + succeedCount + " 個檔案\n" +
unZipFailedCount + " 個檔案解壓失敗,以下是失敗原因:"
);
Set<Map.Entry<File, Exception>> failedElement = unZipFailedMap.entrySet();
for (Map.Entry<File, Exception> fileExceptionEntry : failedElement) {
System.out.println("檔案:" + fileExceptionEntry.getKey() + " 異常:" + fileExceptionEntry.getValue());
}
if (deleteFailedCount > 0) {
System.out.println("另外,還有一些檔案刪除失敗,可能是在解壓過程中失敗了導致它們不被刪除,它們是:");
for (File file : deleteFailedNameList) {
System.out.println(file);
}
}
break;
}
}
}
}else{
System.out.println("提供的工作路徑不準確");
}
}
private static void input() {
System.out.println("提供一個工作路徑:");
workPath = SCANNER.nextLine();
System.out.println("成功解壓完成後是否刪除原始檔(true / false):");
isDelete = SCANNER.nextLine();
}
}
class UnZipFile extends Thread {
private final ConcurrentLinkedQueue<File> zipQueue;
private static final int BUFFER_SIZE = 2 * 1024;
public UnZipFile(ConcurrentLinkedQueue<File> zipQueue) {
this.zipQueue = zipQueue;
}
@Override
public void run() {
do {
if (!zipQueue.isEmpty()) {
File file = zipQueue.poll();
String fileName = file.getName();
File destPathName = new File(file.getParent(), fileName.substring(0, fileName.indexOf(".")));
System.out.println(destPathName.mkdirs());
unZip(file, destPathName.toString());
}
} while (!UnZip.isFlag);
}
public void unZip(File srcFile, String destDirPath) throws RuntimeException {
long start = System.currentTimeMillis();
// 開始解壓
ZipFile zipFile = null;
FileOutputStream fos = null;
InputStream is = null;
try {
zipFile = new ZipFile(srcFile, Charset.forName("GBK"));
Enumeration<?> entries = zipFile.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = (ZipEntry) entries.nextElement();
File unZipPathName = new File(entry.getName());
if (!unZipPathName.isDirectory()){
if (unZipPathName.getName().contains(".zip")) {
zipQueue.add(new File(srcFile.getParentFile(), unZipPathName.toString()));
System.out.println("俄羅斯套娃檔案:" + unZipPathName);
}
}
System.out.println("解壓:" + unZipPathName);
// 如果是資料夾,就建立個資料夾
if (entry.isDirectory()) {
String dirPath = destDirPath + File.separator + entry.getName();
File dir = new File(dirPath);
if(dir.mkdirs()){
System.out.println("No need to create");
}
} else {
// 如果是檔案,就先建立一個檔案,然後用io流把內容copy過去
File targetFile = new File(destDirPath + File.separator + entry.getName());
// 保證這個檔案的父資料夾必須要存在
if(!targetFile.getParentFile().exists()){
if(targetFile.getParentFile().mkdirs()){
System.out.println("No need to create");
}
}
if (targetFile.createNewFile()){
System.out.println("No need to create");
}
// 將壓縮檔案內容寫入到這個檔案中
is = zipFile.getInputStream(entry);
fos = new FileOutputStream(targetFile);
int len;
byte[] buf = new byte[BUFFER_SIZE];
while ((len = is.read(buf)) != -1) {
fos.write(buf, 0, len);
}
fos.flush();
if (Boolean.parseBoolean(UnZip.isDelete)){
if(srcFile.delete()){
System.out.println("成功刪除:" + srcFile);
}else{
UnZip.deleteFailedNameList.add(srcFile);
UnZip.deleteFailedCount++;
}
}
}
}
long end = System.currentTimeMillis();
UnZip.succeedCount++;
System.out.println("解壓完成,耗時:" + (end - start) +" ms");
} catch (Exception e) {
e.printStackTrace();
UnZip.unZipFailedCount++;
UnZip.unZipFailedMap.put(srcFile, e);
} finally {
if(zipFile != null){
try {
zipFile.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fos != null){
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (is != null){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
class FindZipFile extends Thread {
private final File file;
public FindZipFile(File file) {
this.file = file;
}
@Override
public void run() {
find(file);
}
public void find(File path){
File[] files = path.listFiles();
if (files != null) {
for (File file : files) {
if (file.isDirectory()){
find(file);
}else{
UnZip.foundCount++;
String absolutePath = file.getAbsolutePath();
String[] split = absolutePath.split("\\.");
if ("zip".equalsIgnoreCase(split[split.length - 1])){
UnZip.ZIP_QUEUE.add(file);
}
}
}
}
}
}