歡迎大家關(guān)注本博,同時(shí)歡迎大家評(píng)論交流,可以給個(gè)贊哦!!!
GZip是常用的無(wú)損壓縮算法實(shí)現(xiàn),在Linux中較為常見,像我們?cè)贚inux安裝軟件時(shí),基本都是.tar.gz格式。.tar.gz格式文件需要先對(duì)目錄內(nèi)文件進(jìn)行tar壓縮,然后使用GZip進(jìn)行壓縮。
本文針對(duì)基于磁盤的壓縮和解壓進(jìn)行演示,演示只針對(duì)一層目錄結(jié)構(gòu)進(jìn)行,多層目錄只需遞歸操作進(jìn)行即可。
Maven依賴
org.apache.commons: commons-compress: 1.19: 此依賴封裝了很多壓縮算法相關(guān)的工具類,提供的API還是相對(duì)比較底層,我們今天在它的基礎(chǔ)上做進(jìn)一步封裝。
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> |
工具類
在實(shí)際應(yīng)用中,對(duì)應(yīng)不同需求,可能需要生成若干文件,然后將其壓縮。在某些應(yīng)用中,文件較小、文件數(shù)量較少且較為固定,頻繁與磁盤操作,會(huì)帶來(lái)不必要的效率影響。
工具類針對(duì).tar.gz格式提供了compressByTar、decompressByTar、compressByGZip、decompressByGZip四個(gè)方法,用于處理.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 基于內(nèi)存以ZIP算法進(jìn)行壓縮和解壓工具類. */ public class GZipRamUtil { /** * 使用TAR算法進(jìn)行壓縮. * @param sourceFileBytesMap 待壓縮文件的Map集合. * @return 壓縮后的TAR文件字節(jié)數(shù)組. * @throws Exception 壓縮過(guò)程中可能發(fā)生的異常,若發(fā)生異常,則返回的字節(jié)數(shù)組長(zhǎng)度為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算法進(jìn)行解壓. * @param sourceZipFileBytes TAR文件字節(jié)數(shù)組. * @return 解壓后的文件Map集合. * @throws Exception 解壓過(guò)程中可能發(fā)生的異常,若發(fā)生異常,返回Map集合長(zhǎng)度為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算法進(jìn)行壓縮. * @param sourceFileBytesMap 待壓縮文件的Map集合. * @return 壓縮后的GZIP文件字節(jié)數(shù)組. * @throws Exception 壓縮過(guò)程中可能發(fā)生的異常,若發(fā)生異常,則返回的字節(jié)數(shù)組長(zhǎng)度為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提供的方式進(jìn)行壓縮. gzipGcos.write(sourceFileBytes); } finally { if (gzipGcos != null ) { gzipGcos.close(); } if ( null == gzipBaos) { gzipBaos = new ByteArrayOutputStream(); } } return gzipBaos.toByteArray(); } /** * 使用GZIP算法進(jìn)行解壓. * @param sourceGZipFileBytes GZIP文件字節(jié)數(shù)組. * @return 解壓后的文件Map集合. * @throws Exception 解壓過(guò)程中可能發(fā)生的異常,若發(fā)生異常,則返回的字節(jié)數(shù)組長(zhǎng)度為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提供的方式進(jìn)行解壓. gzipBaos.write(IOUtils.toByteArray(sourceGZipGcis)); } finally { if (sourceGZipGcis != null ) sourceGZipGcis.close(); } return gzipBaos.toByteArray(); } } |
工具類測(cè)試
在Maven依賴引入正確的情況下,復(fù)制上面的代碼到項(xiàng)目中,修改package,可以直接使用,下面我們對(duì)工具類進(jìn)行簡(jiǎn)單測(cè)試。測(cè)試類代碼如下:
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工具類測(cè)試. */ public class GZipRamUtilTester { public static void main(String[] args) throws Exception { Map<String, byte []> fileBytesMap = null ; fileBytesMap = new HashMap<String, byte []>(); // 設(shè)置文件列表. File dirFile = new File( "C:/Users/Administrator/Downloads/個(gè)人文件/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/個(gè)人文件/2020-07-13/ram.tar.gz" ), ramBytes); ramBytes = GZipRamUtil.decompressByGZip(ramBytes); fileBytesMap = GZipRamUtil.decompressByTar(ramBytes); System.out.println(fileBytesMap.size()); } } |
運(yùn)行測(cè)試后,通過(guò)查看ram.tar.gz和控制臺(tái)輸出解壓后文件數(shù)量,可以確認(rèn)工具類運(yùn)行結(jié)果無(wú)誤。
總結(jié)
1) 在小文件、文件數(shù)量較小且較為固定時(shí),提倡使用內(nèi)存壓縮和解壓方式。使用內(nèi)存換時(shí)間,減少頻繁的磁盤操作。
2) 在大文件、文件數(shù)量較大時(shí),提倡使用磁盤壓縮和解壓方式。過(guò)大文件對(duì)服務(wù)會(huì)造成過(guò)度的負(fù)載,磁盤壓縮和解壓可以緩解這種壓力?!?a href="/article/70656.html">Java GZip 基于磁盤實(shí)現(xiàn)壓縮和解壓》
到此這篇關(guān)于Java GZip 基于內(nèi)存實(shí)現(xiàn)壓縮和解壓的文章就介紹到這了,更多相關(guān)Java GZip 實(shí)現(xiàn)壓縮和解壓內(nèi)容請(qǐng)搜索服務(wù)器之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持服務(wù)器之家!
原文鏈接:https://blog.csdn.net/securitit/article/details/108156074