Java GZip 基于磁盤實現(xiàn)壓縮和解壓的方法
GZip是常用的無損壓縮算法實現(xiàn),在Linux中較為常見,像我們在Linux安裝軟件時,基本都是.tar.gz格式。.tar.gz格式文件需要先對目錄內(nèi)文件進行tar壓縮,然后使用GZip進行壓縮。
本文針對基于磁盤的壓縮和解壓進行演示,演示只針對一層目錄結(jié)構(gòu)進行,多層目錄只需遞歸操作進行即可。
Maven依賴
org.apache.commons: commons-compress: 1.19: 此依賴封裝了很多壓縮算法相關(guān)的工具類,提供的API還是相對比較底層,我們今天在它的基礎(chǔ)上做進一步封裝。
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-compress</artifactId> <version>1.19</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency>
工具類
其實,在通常情況下,我們都是在磁盤上進行壓縮和解壓操作的,這樣雖然增加了操作的復雜度,但是卻無形中避免了一些問題。
工具類針對.tar.gz格式提供了compressByTar、decompressByTar、compressByGZip、decompressByGZip四個方法,用于處理.tar.gz格式壓縮文件,代碼如下:
package com.arhorchin.securitit.compress.gzip;
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 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.compressors.gzip.GzipCompressorInputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream;
import org.apache.commons.compress.utils.IOUtils;
import org.apache.log4j.Logger;
/**
* @author Securitit.
* @note 基于磁盤以GZIP算法進行壓縮和解壓工具類.
*/
public class GZipDiskUtil {
/**
* logger.
*/
private static Logger logger = Logger.getLogger(GZipDiskUtil.class);
/**
* UTF-8字符集.
*/
public static String CHARSET_UTF8 = "UTF-8";
/**
* 使用TAR算法進行壓縮.
* @param sourceFolderPath 待進行壓縮的文件夾路徑.
* @param targetTarFilePath 壓縮后的TAR文件存儲目錄.
* @return 壓縮是否成功.
* @throws Exception 壓縮過程中可能發(fā)生的異常.
*/
public static boolean compressByTar(String sourceFolderPath, String targetTarFilePath) throws Exception {
// 變量定義.
File sourceFolderFile = null;
FileOutputStream targetTarFos = null;
TarArchiveOutputStream targetTartTaos = null;
TarArchiveEntry targetTarTae = null;
try {
// 壓縮變量初始化.
sourceFolderFile = new File(sourceFolderPath);
targetTarFos = new FileOutputStream(new File(targetTarFilePath));
targetTartTaos = new TarArchiveOutputStream(targetTarFos);
// 將文件添加到ZIP條目中.
for (File file : sourceFolderFile.listFiles()) {
try (FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);) {
targetTarTae = new TarArchiveEntry(file);
targetTarTae.setName(file.getName());
targetTartTaos.putArchiveEntry(targetTarTae);
targetTartTaos.write(IOUtils.toByteArray(bis));
targetTartTaos.closeArchiveEntry();
}
}
} catch (Exception ex) {
logger.info("GZipDiskUtil.compressByTar.", ex);
return false;
} finally {
if (targetTartTaos != null)
targetTartTaos.close();
if (targetTarFos != null)
targetTarFos.close();
}
return true;
}
/**
* 使用TAR算法進行解壓.
* @param sourceTarPath 待解壓文件路徑.
* @param targetFolderPath 解壓后文件夾目錄.
* @return 解壓是否成功.
* @throws Exception 解壓過程中可能發(fā)生的異常.
*/
public static boolean decompressByTar(String sourceTarPath, String targetFolderPath) throws Exception {
// 變量定義.
FileInputStream sourceTarFis = null;
TarArchiveInputStream sourceTarTais = null;
TarArchiveEntry sourceTarTae = null;
File singleEntryFile = null;
try {
// 解壓定義初始化.
sourceTarFis = new FileInputStream(new File(sourceTarPath));
sourceTarTais = new TarArchiveInputStream(sourceTarFis);
// 條目解壓縮至指定文件夾目錄下.
while ((sourceTarTae = sourceTarTais.getNextTarEntry()) != null) {
singleEntryFile = new File(targetFolderPath + File.separator + sourceTarTae.getName());
try (FileOutputStream fos = new FileOutputStream(singleEntryFile);
BufferedOutputStream bos = new BufferedOutputStream(fos);) {
bos.write(IOUtils.toByteArray(sourceTarTais));
}
}
} catch (Exception ex) {
logger.info("GZipDiskUtil.decompressByTar.", ex);
return false;
} finally {
if (sourceTarTais != null)
sourceTarTais.close();
if (sourceTarFis != null)
sourceTarFis.close();
}
return true;
}
/**
* 使用GZIP算法進行壓縮.
* @param sourceFilePath 待進行壓縮的文件路徑.
* @param targetGZipFilePath 壓縮后的GZIP文件存儲目錄.
* @return 壓縮是否成功.
* @throws Exception 壓縮過程中可能發(fā)生的異常.
*/
public static boolean compressByGZip(String sourceFilePath, String targetGZipFilePath) throws IOException {
// 變量定義.
FileInputStream sourceFileFis = null;
BufferedInputStream sourceFileBis = null;
FileOutputStream targetGZipFileFos = null;
BufferedOutputStream targetGZipFileBos = null;
GzipCompressorOutputStream targetGZipFileGcos = null;
try {
// 壓縮變量初始化.
sourceFileFis = new FileInputStream(new File(sourceFilePath));
sourceFileBis = new BufferedInputStream(sourceFileFis);
targetGZipFileFos = new FileOutputStream(targetGZipFilePath);
targetGZipFileBos = new BufferedOutputStream(targetGZipFileFos);
targetGZipFileGcos = new GzipCompressorOutputStream(targetGZipFileBos);
// 采用commons-compress提供的方式進行壓縮.
targetGZipFileGcos.write(IOUtils.toByteArray(sourceFileBis));
} catch (Exception ex) {
logger.info("GZipDiskUtil.compressByGZip.", ex);
return false;
} finally {
if (targetGZipFileGcos != null)
targetGZipFileGcos.close();
if (targetGZipFileBos != null)
targetGZipFileBos.close();
if (targetGZipFileFos != null)
targetGZipFileFos.close();
if (sourceFileBis != null)
sourceFileBis.close();
if (sourceFileFis != null)
sourceFileFis.close();
}
return true;
}
/**
* 使用GZIP算法進行解壓.
* @param sourceGZipFilePath 待解壓文件路徑.
* @param targetFilePath 解壓后文件路徑.
* @return 解壓是否成功.
* @throws @throws Exception 解壓過程中可能發(fā)生的異常.
*/
public static boolean decompressByGZip(String sourceGZipFilePath, String targetFilePath) throws IOException {
// 變量定義.
FileInputStream sourceGZipFileFis = null;
BufferedInputStream sourceGZipFileBis = null;
FileOutputStream targetFileFos = null;
GzipCompressorInputStream sourceGZipFileGcis = null;
try {
// 解壓變量初始化.
sourceGZipFileFis = new FileInputStream(new File(sourceGZipFilePath));
sourceGZipFileBis = new BufferedInputStream(sourceGZipFileFis);
sourceGZipFileGcis = new GzipCompressorInputStream(sourceGZipFileBis);
targetFileFos = new FileOutputStream(new File(targetFilePath));
// 采用commons-compress提供的方式進行解壓.
targetFileFos.write(IOUtils.toByteArray(sourceGZipFileGcis));
} catch (Exception ex) {
logger.info("GZipDiskUtil.decompressByGZip.", ex);
return false;
} finally {
if (sourceGZipFileGcis != null)
sourceGZipFileGcis.close();
if (sourceGZipFileBis != null)
sourceGZipFileBis.close();
if (sourceGZipFileFis != null)
sourceGZipFileFis.close();
if (targetFileFos != null)
targetFileFos.close();
}
return true;
}
}
工具類測試
在Maven依賴引入正確的情況下,復制上面的代碼到項目中,修改package,可以直接使用,下面我們對工具類進行簡單測試。測試類代碼如下:
package com.arhorchin.securitit.compress.gzip;
import com.arhorchin.securitit.compress.gzip.GZipDiskUtil;
/**
* @author Securitit.
* @note GZipDiskUtil工具類測試.
*/
public class GZipDiskUtilTester {
public static void main(String[] args) throws Exception {
GZipDiskUtil.compressByTar("C:/Users/Administrator/Downloads/個人文件/2020-07-13/files", "C:/Users/Administrator/Downloads/個人文件/2020-07-13/disk.tar");
GZipDiskUtil.compressByGZip("C:/Users/Administrator/Downloads/個人文件/2020-07-13/disk.tar", "C:/Users/Administrator/Downloads/個人文件/2020-07-13/disk.tar.gz");
GZipDiskUtil.decompressByGZip("C:/Users/Administrator/Downloads/個人文件/2020-07-13/disk.tar.gz", "C:/Users/Administrator/Downloads/個人文件/2020-07-13/disk-untar.tar");
GZipDiskUtil.decompressByTar("C:/Users/Administrator/Downloads/個人文件/2020-07-13/disk-untar.tar", "C:/Users/Administrator/Downloads/個人文件/2020-07-13/disk-untar");
}
}
運行測試后,通過查看disk.tar、disk.tar.gz、disk-untar.tar和解壓的目錄,可以確認工具類運行結(jié)果無誤。
總結(jié)
1) 在小文件、文件數(shù)量較小且較為固定時,提倡使用內(nèi)存壓縮和解壓方式。使用內(nèi)存換時間,減少頻繁的磁盤操作。《Java GZip 基于內(nèi)存實現(xiàn)壓縮和解壓》
2) 在大文件、文件數(shù)量較大時,提倡使用磁盤壓縮和解壓方式。過大文件對服務會造成過度的負載,磁盤壓縮和解壓可以緩解這種壓力。
- java工具類實現(xiàn)文件壓縮zip以及解壓縮功能
- Java實現(xiàn)解壓zip和rar包的示例代碼
- Java壓縮和解壓縮ZIP文件實戰(zhàn)案例
- Java實現(xiàn)文件壓縮為zip和解壓zip壓縮包
- Java如何不解壓讀取.zip的文件內(nèi)容
- Java中zip的壓縮和解壓縮的實現(xiàn)代碼
- 用Java進行zip文件壓縮與解壓縮
- Java GZip 基于內(nèi)存實現(xiàn)壓縮和解壓的方法
- 使用java API實現(xiàn)zip遞歸壓縮和解壓文件夾
- 如何基于java實現(xiàn)解壓ZIP TAR等文件
- Java實現(xiàn)解壓zip壓縮包的兩種方法(支持多層級)
相關(guān)文章
SpringBoot2.0.3打印默認數(shù)據(jù)源為 HikariDataSource (null)問題
這篇文章主要介紹了SpringBoot2.0.3打印默認數(shù)據(jù)源為 HikariDataSource (null)問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-10-10
如何動態(tài)改變Retrofit的base url和rest版本詳解
這篇文章主要給大家介紹了關(guān)于如何動態(tài)改變Retrofit的base url和rest版本的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2018-09-09
Java插入修改刪除數(shù)據(jù)庫數(shù)據(jù)的基本方法
這篇文章主要介紹了Java插入修改刪除數(shù)據(jù)庫數(shù)據(jù)的基本方法,是Java入門學習中的基礎(chǔ)知識,需要的朋友可以參考下2015-10-10
Java實現(xiàn)的獲取和判斷文件頭信息工具類用法示例
這篇文章主要介紹了Java實現(xiàn)的獲取和判斷文件頭信息工具類,結(jié)合實例形式分析了Java針對文件讀取及頭信息判斷相關(guān)操作技巧,需要的朋友可以參考下2017-11-11
BeanUtils.copyProperties擴展--實現(xiàn)String轉(zhuǎn)Date
這篇文章主要介紹了BeanUtils.copyProperties擴展--實現(xiàn)String轉(zhuǎn)Date操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06

