1. 程式人生 > >java實現對zip、tar、gzip(gz)的壓縮與解壓

java實現對zip、tar、gzip(gz)的壓縮與解壓

以下是一個工具類:


import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream;

/**
 * 壓縮、解壓 -> 工具類
 * 更多示例,可見官網:http://commons.apache.org/proper/commons-compress/examples.html
 * 總體說明:如果有同名的檔案,那麼壓縮/解壓後的檔案將會覆蓋原來的檔案
 *
 * @author JustryDeng
 * @DATE 2018年9月25日 下午12:26:47
 */
public class CompressionAndDecompressionUtils {

	public static void main(String[]args){
		try {
			String[] filesPathArray={"D:/data/file/mock3.log","D:/data/file/mock4.log","D:/data/file/mock5.log"};
			tarCompression(filesPathArray,"D:/data/file/ceshi.tar");
			gzipCompression("D:/data/file/ceshi.tar","D:/data/file/ceshi.tar.gz");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * tar打包壓縮
	 *
	 * @param filesPathArray
	 *            要壓縮的檔案的全路徑(陣列)
	 * @param resultFilePath
	 *            壓縮後的檔案全檔名(.tar)
	 * @throws Exception
	 * @DATE 2018年9月25日 下午12:39:28
	 */
	public static boolean tarCompression(String[] filesPathArray, String resultFilePath) throws Exception {
		System.out.println(" tarCompression -> Compression start!");
		FileOutputStream fos = null;
		TarArchiveOutputStream taos = null;
		try {
			fos = new FileOutputStream(new File(resultFilePath));
			taos = new TarArchiveOutputStream(fos);
			for (String filePath : filesPathArray) {
				BufferedInputStream bis = null;
				FileInputStream fis = null;
				try {
					File file = new File(filePath);
					TarArchiveEntry tae = new TarArchiveEntry(file);
					// 此處指明 每一個被壓縮檔案的名字,以便於解壓時TarArchiveEntry的getName()方法獲取到的直接就是這裡指定的檔名
					// 以(左邊的)GBK編碼將file.getName()“打碎”為序列,再“組裝”序列為(右邊的)GBK編碼的字串
					tae.setName(new String(file.getName().getBytes("GBK"), "GBK"));
					taos.putArchiveEntry(tae);
					fis = new FileInputStream(file);
					bis = new BufferedInputStream(fis);
					int count;
					byte data[] = new byte[1024];
					while ((count = bis.read(data, 0, 1024)) != -1) {
						taos.write(data, 0, count);
					}
				} finally {
					taos.closeArchiveEntry();
					if (bis != null)
						bis.close();
					if (fis != null)
						fis.close();
				}
			}
		} finally {
			if (taos != null)
				taos.close();
			if (fos != null)
				fos.close();

		}
		System.out.println(" tarCompression -> Compression end!");
		return true;
	}

	/**
	 * tar拆包解壓
	 *
	 * @param decompressFilePath
	 *            要被解壓的壓縮檔案 全路徑
	 * @param resultDirPath
	 *            解壓檔案存放絕對路徑(目錄)
	 * @throws Exception
	 * @DATE 2018年9月25日 下午12:39:43
	 */
	public static boolean tarDecompression(String decompressFilePath, String resultDirPath) throws Exception {
		System.out.println(" tarDecompression -> Decompression start!");
		TarArchiveInputStream tais = null;
		FileInputStream fis = null;
		try {
			File file = new File(decompressFilePath);
			fis = new FileInputStream(file);
			tais = new TarArchiveInputStream(fis);
			TarArchiveEntry tae = null;
			while ((tae = tais.getNextTarEntry()) != null) {
				BufferedOutputStream bos = null;
				FileOutputStream fos = null;
				try {
					System.out.println("  already decompression file -> " + tae.getName());
					String dir = resultDirPath + File.separator + tae.getName();// tar檔中檔案
					File dirFile = new File(dir);
					fos = new FileOutputStream(dirFile);
					bos = new BufferedOutputStream(fos);
					int count;
					byte data[] = new byte[1024];
					while ((count = tais.read(data, 0, 1024)) != -1) {
						bos.write(data, 0, count);
					}
				} finally {
					if (bos != null)
						bos.close();
					if (fos != null)
						fos.close();
				}
			}
		} finally {
			if (tais != null)
				tais.close();
			if (fis != null)
				fis.close();
		}
		System.out.println(" tarDecompression -> Decompression end!");
		return true;
	}

	/**
	 * 對.tar檔案進行gzip壓縮
	 * 說明:我們一般先把多個檔案tar打包為一個,然後再使用gzip進行壓縮; 進而獲得形如“abc.tar.gz”這樣的壓縮檔案
	 *  注:這裡暫時不再深入學習,以後有閒暇時間可深入瞭解如何壓縮多個檔案等
	 *  注:如果明確知道解壓後的是什麼型別的檔案;那麼可以直接指定解壓後的檔案型別(實際上也需要這麼做);
	 *     .tar.gz 解壓後就是.tar檔案,所以我們在解壓時,給出的解壓後的檔案的全路徑名就是以.tar結尾的
	 * @param filePath
	 *            要被壓縮的壓縮檔案 全路徑
	 * @param resultFilePath
	 *            壓縮後的檔案(全檔名 .gz)
	 * @throws IOException
	 * @DATE 2018年9月25日 下午2:50:22
	 */
	public static boolean gzipCompression(String filePath, String resultFilePath) throws IOException {
		System.out.println(" gzipCompression -> Compression start!");
		InputStream fin = null;
		BufferedInputStream bis = null;
		FileOutputStream fos = null;
		BufferedOutputStream bos= null;
		GzipCompressorOutputStream gcos = null;
		try {
			fin = Files.newInputStream(Paths.get(filePath));
			bis = new BufferedInputStream(fin);
			fos = new FileOutputStream(resultFilePath);
			bos = new BufferedOutputStream(fos);
			gcos = new GzipCompressorOutputStream(bos);
			byte[] buffer = new byte[1024];
			int read = -1;
			while ((read = bis.read(buffer)) != -1) {
				gcos.write(buffer, 0, read);
			}
		} finally {
			if(gcos != null)
				gcos.close();
			if(bos != null)
				bos.close();
			if(fos != null)
				fos.close();
			if(bis != null)
				bis.close();
			if(fin != null)
				fin.close();
		}
		System.out.println(" gzipCompression -> Compression end!");
		return true;
	}

	/**
	 * 解壓對.tar.gz檔案至 .tar檔案
	 * 說明:我們一般都是對.tar.gz檔案進行gzip解壓; 進而獲得形如.tar檔案;再進行解壓
	 *   注:這裡暫時不再深入學習,以後有閒暇時間可深入瞭解學習
	 *
	 * @param compressedFilePath
	 *            要被解壓的壓縮檔案 全路徑
	 * @param resultDirPath
	 *            解壓檔案存放絕對路徑(目錄)
	 * @throws IOException
	 * @DATE 2018年9月25日 下午4:35:09
	 */
	public static  boolean gzipDecompression(String compressedFilePath, String resultDirPath) throws IOException {
		System.out.println(" gzipDecompression -> Compression start!");
		InputStream fin = null;
		BufferedInputStream in = null;
		OutputStream out = null;
		GzipCompressorInputStream gcis = null;
		try {
			out = Files.newOutputStream(Paths.get(resultDirPath));
			fin = Files.newInputStream(Paths.get(compressedFilePath));
			in = new BufferedInputStream(fin);
			gcis = new GzipCompressorInputStream(in);
			final byte[] buffer = new byte[1024];
			int n = 0;
			while (-1 != (n = gcis.read(buffer))) {
				out.write(buffer, 0, n);
			}
		} finally {
			if(gcis != null)
				gcis.close();
			if(in != null)
				in.close();
			if(fin != null)
				fin.close();
			if(out != null)
				out.close();
		}
		System.out.println(" gzipDecompression -> Compression end!");
		return true;
	}


	/**
	 * zip壓縮(注:與tar類似)
	 *
	 * @param filesPathArray
	 *            要壓縮的檔案的全路徑(陣列)
	 * @param resultFilePath
	 *            壓縮後的檔案全檔名(.tar)
	 * @throws Exception
	 * @DATE 2018年9月25日 下午17:55:28
	 */
	public static boolean zipCompression(String[] filesPathArray, String resultFilePath) throws Exception {
		System.out.println(" zipCompression -> Compression start!");
		ZipArchiveOutputStream zaos = null;
		FileOutputStream fos = null;
		try {
			fos = new FileOutputStream(new File(resultFilePath));
			zaos = new ZipArchiveOutputStream(fos);
			for (String filePath : filesPathArray) {
				FileInputStream fis = null;
				BufferedInputStream bis = null;
				try {
					File file = new File(filePath);
					// 第二個引數如果是檔案全路徑名,那麼壓縮時也會將路徑資料夾也縮排去;
					// 我們之壓縮目標檔案,而不壓縮該檔案所處位置的相關資料夾,所以這裡我們用file.getName()
					ZipArchiveEntry zae = new ZipArchiveEntry(file, file.getName());
					zaos.putArchiveEntry(zae);
					fis = new FileInputStream(file);
					bis = new BufferedInputStream(fis);
					int count;
					byte data[] = new byte[1024];
					while ((count = bis.read(data, 0, 1024)) != -1) {
						zaos.write(data, 0, count);
					}
				} finally {
					zaos.closeArchiveEntry();
					if (bis != null)
						bis.close();
					if (fis != null)
						fis.close();
				}

			}
		} finally {
			if (zaos != null)
				zaos.close();
			if (fos != null)
				fos.close();
		}
		System.out.println(" zipCompression -> Compression end!");
		return true;
	}

	/**
	 * zip解壓(注:與tar類似)
	 *
	 * @param decompressFilePath
	 *            要被解壓的壓縮檔案 全路徑
	 * @param resultDirPath
	 *            解壓檔案存放絕對路徑(目錄)
	 * @throws Exception
	 * @DATE 2018年9月25日 下午18:39:43
	 */
	public static boolean zipDecompression(String decompressFilePath, String resultDirPath) throws Exception {
		System.out.println(" zipDecompression -> Decompression start!");
		ZipArchiveInputStream zais = null;
		FileInputStream fis = null;
		try {
			File file = new File(decompressFilePath);
			fis = new FileInputStream(file);
			zais = new ZipArchiveInputStream(fis);
			ZipArchiveEntry zae = null;
			while ((zae = zais.getNextZipEntry()) != null) {
				FileOutputStream fos = null;
				BufferedOutputStream bos = null;
				try {
					System.out.println("  already decompression file -> " + zae.getName());
					String dir = resultDirPath + File.separator + zae.getName();// tar檔中檔案
					File dirFile = new File(dir);
					fos = new FileOutputStream(dirFile);
					bos = new BufferedOutputStream(fos);
					int count;
					byte data[] = new byte[1024];
					while ((count = zais.read(data, 0, 1024)) != -1) {
						bos.write(data, 0, count);
					}
				} finally {
					if (bos != null)
						bos.close();
					if (fos != null)
						fos.close();
				}
			}
		} finally {
			if (zais != null)
				zais.close();
			if (fis != null)
				fis.close();
		}
		System.out.println(" zipDecompression -> Decompression end!");
		return true;
	}

}

在pom.xml需要引入的依賴:

<dependency>
   <groupId>org.apache.commons</groupId>
   <artifactId>commons-compress</artifactId>
   <version>1.9</version>
</dependency>