歡迎大家關注本博,同時歡迎大家評論交流,可以給個贊哦!!!
GZip是常用的無損壓縮算法實現,在Linux中較為常見,像我們在Linux安裝軟件時,基本都是.tar.gz格式。.tar.gz格式文件需要先對目錄內文件進行tar壓縮,然后使用GZip進行壓縮。
本文針對基于磁盤的壓縮和解壓進行演示,演示只針對一層目錄結構進行,多層目錄只需遞歸操作進行即可。
Maven依賴
org.apache.commons: commons-compress: 1.19: 此依賴封裝了很多壓縮算法相關的工具類,提供的API還是相對比較底層,我們今天在它的基礎上做進一步封裝。
1
2
3
4
5
6
7
8
9
10
|
<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格式壓縮文件,代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
|
package com.arhorchin.securitit.compress.gzip; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.HashMap; import java.util.Map; 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.io.IOUtils; /** * @author Securitit. * @note 基于內存以ZIP算法進行壓縮和解壓工具類. */ public class GZipRamUtil { /** * 使用TAR算法進行壓縮. * @param sourceFileBytesMap 待壓縮文件的Map集合. * @return 壓縮后的TAR文件字節數組. * @throws Exception 壓縮過程中可能發生的異常,若發生異常,則返回的字節數組長度為0. */ public static byte [] compressByTar(Map<String, byte []> tarFileBytesMap) throws Exception { // 變量定義. ByteArrayOutputStream tarBaos = null ; TarArchiveOutputStream tarTaos = null ; TarArchiveEntry tarTae = null ; try { // 壓縮變量初始化. tarBaos = new ByteArrayOutputStream(); tarTaos = new TarArchiveOutputStream(tarBaos); // // 將文件添加到TAR條目中. for (Map.Entry<String, byte []> fileEntry : tarFileBytesMap.entrySet()) { tarTae = new TarArchiveEntry(fileEntry.getKey()); tarTae.setName(fileEntry.getKey()); tarTae.setSize(fileEntry.getValue().length); tarTaos.putArchiveEntry(tarTae); tarTaos.write(fileEntry.getValue()); tarTaos.closeArchiveEntry(); } } finally { if (tarTaos != null ) { tarTaos.close(); } if ( null == tarBaos) { tarBaos = new ByteArrayOutputStream(); } } return tarBaos.toByteArray(); } /** * 使用TAR算法進行解壓. * @param sourceZipFileBytes TAR文件字節數組. * @return 解壓后的文件Map集合. * @throws Exception 解壓過程中可能發生的異常,若發生異常,返回Map集合長度為0. */ public static Map<String, byte []> decompressByTar( byte [] sourceTarFileBytes) throws Exception { // 變量定義. TarArchiveEntry sourceTarTae = null ; ByteArrayInputStream sourceTarBais = null ; TarArchiveInputStream sourceTarTais = null ; Map<String, byte []> targetFilesFolderMap = null ; try { // 解壓變量初始化. targetFilesFolderMap = new HashMap<String, byte []>(); sourceTarBais = new ByteArrayInputStream(sourceTarFileBytes); sourceTarTais = new TarArchiveInputStream(sourceTarBais); // 條目解壓縮至Map中. while ((sourceTarTae = sourceTarTais.getNextTarEntry()) != null ) { targetFilesFolderMap.put(sourceTarTae.getName(), IOUtils.toByteArray(sourceTarTais)); } } finally { if (sourceTarTais != null ) sourceTarTais.close(); } return targetFilesFolderMap; } /** * 使用GZIP算法進行壓縮. * @param sourceFileBytesMap 待壓縮文件的Map集合. * @return 壓縮后的GZIP文件字節數組. * @throws Exception 壓縮過程中可能發生的異常,若發生異常,則返回的字節數組長度為0. */ public static byte [] compressByGZip( byte [] sourceFileBytes) throws IOException { // 變量定義. ByteArrayOutputStream gzipBaos = null ; GzipCompressorOutputStream gzipGcos = null ; try { // 壓縮變量初始化. gzipBaos = new ByteArrayOutputStream(); gzipGcos = new GzipCompressorOutputStream(gzipBaos); // 采用commons-compress提供的方式進行壓縮. gzipGcos.write(sourceFileBytes); } finally { if (gzipGcos != null ) { gzipGcos.close(); } if ( null == gzipBaos) { gzipBaos = new ByteArrayOutputStream(); } } return gzipBaos.toByteArray(); } /** * 使用GZIP算法進行解壓. * @param sourceGZipFileBytes GZIP文件字節數組. * @return 解壓后的文件Map集合. * @throws Exception 解壓過程中可能發生的異常,若發生異常,則返回的字節數組長度為0. */ public static byte [] decompressByGZip( byte [] sourceGZipFileBytes) throws IOException { // 變量定義. ByteArrayOutputStream gzipBaos = null ; ByteArrayInputStream sourceGZipBais = null ; GzipCompressorInputStream sourceGZipGcis = null ; try { // 解壓變量初始化. gzipBaos = new ByteArrayOutputStream(); sourceGZipBais = new ByteArrayInputStream(sourceGZipFileBytes); sourceGZipGcis = new GzipCompressorInputStream(sourceGZipBais); // 采用commons-compress提供的方式進行解壓. gzipBaos.write(IOUtils.toByteArray(sourceGZipGcis)); } finally { if (sourceGZipGcis != null ) sourceGZipGcis.close(); } return gzipBaos.toByteArray(); } } |
工具類測試
在Maven依賴引入正確的情況下,復制上面的代碼到項目中,修改package,可以直接使用,下面我們對工具類進行簡單測試。測試類代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
package com.arhorchin.securitit.compress.gzip; import java.io.File; import java.util.HashMap; import java.util.Map; import org.apache.commons.io.FileUtils; import com.arhorchin.securitit.compress.gzip.GZipRamUtil; /** * @author Securitit. * @note GZipRamUtil工具類測試. */ public class GZipRamUtilTester { public static void main(String[] args) throws Exception { Map<String, byte []> fileBytesMap = null ; fileBytesMap = new HashMap<String, byte []>(); // 設置文件列表. File dirFile = new File( "C:/Users/Administrator/Downloads/個人文件/2020-07-13/files" ); for (File file : dirFile.listFiles()) { fileBytesMap.put(file.getName(), FileUtils.readFileToByteArray(file)); } byte [] ramBytes = GZipRamUtil.compressByTar(fileBytesMap); ramBytes = GZipRamUtil.compressByGZip(ramBytes); FileUtils.writeByteArrayToFile( new File( "C:/Users/Administrator/Downloads/個人文件/2020-07-13/ram.tar.gz" ), ramBytes); ramBytes = GZipRamUtil.decompressByGZip(ramBytes); fileBytesMap = GZipRamUtil.decompressByTar(ramBytes); System.out.println(fileBytesMap.size()); } } |
運行測試后,通過查看ram.tar.gz和控制臺輸出解壓后文件數量,可以確認工具類運行結果無誤。
總結
1) 在小文件、文件數量較小且較為固定時,提倡使用內存壓縮和解壓方式。使用內存換時間,減少頻繁的磁盤操作。
2) 在大文件、文件數量較大時,提倡使用磁盤壓縮和解壓方式。過大文件對服務會造成過度的負載,磁盤壓縮和解壓可以緩解這種壓力。《Java GZip 基于磁盤實現壓縮和解壓》
到此這篇關于Java GZip 基于內存實現壓縮和解壓的文章就介紹到這了,更多相關Java GZip 實現壓縮和解壓內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!
原文鏈接:https://blog.csdn.net/securitit/article/details/108156074