Java压缩技术之解压篇,支持:ZIP、RAR、7Z、TAR、GZ、TAR.GZ、BZ2、TAR.BZ2

前言

这篇文章主要讲解Java解压的操作,后续会写一篇关于压缩的文章。

提醒:文章中有些片段看似代码很多,其实去除trycatch、释放资源真正有用的代码没几句,解压其实都很简单,主要用心去观察,都是依葫芦画瓢。

首先,先写一个类似辅助的视图类

1 public enum FileType {

2 // 未知

3 UNKNOWN,

4 // 压缩文件

5 ZIP, RAR, _7Z, TAR, GZ, TAR_GZ, BZ2, TAR_BZ2,

6 // 位图文件

7 BMP, PNG, JPG, JPEG,

8 // 矢量图文件

9 SVG,

10 // 影音文件

11 AVI, MP4, MP3, AAR, OGG, WAV, WAVE

12 }

这个类主要是用来将各种文件的类型集中管理,当然,不写这个类也是可以的,可以直接用字符串去表示。

然后,我还写了一个获取文件真实类型的方法

为什么要写这个方法呢?因为,我们是可以直接去修改文件的后缀的,这样很危险!

1 /**

2 * 获取文件真实类型

3 *

4 * @param file 要获取类型的文件。

5 * @return 文件类型枚举。

6 */

7 private static FileType getFileType(File file){

8 FileInputStream inputStream =null;

9 try{

10 inputStream = new FileInputStream(file);

11 byte[] head = new byte[4];

12 if (-1 == inputStream.read(head)) {

13 return FileType.UNKNOWN;

14 }

15 int headHex = 0;

16 for (byte b : head) {

17 headHex <<= 8;

18 headHex |= b;

19 }

20 switch (headHex) {

21 case 0x504B0304:

22 return FileType.ZIP;

23 case 0x776f7264:

24 return FileType.TAR;

25 case -0x51:

26 return FileType._7Z;

27 case 0x425a6839:

28 return FileType.BZ2;

29 case -0x74f7f8:

30 return FileType.GZ;

31 case 0x52617221:

32 return FileType.RAR;

33 default:

34 return FileType.UNKNOWN;

35 }

36 }catch (Exception e){

37 e.printStackTrace();

38 }finally {

39 try {

40 if(inputStream!=null){

41 inputStream.close();

42 }

43 } catch (IOException e) {

44 e.printStackTrace();

45 }

46 }

47 return FileType.UNKNOWN;

48 }

这里是通过文件头信息来判断什么类型的。其他文件的头文件信息,这里就不展示了。如果有需要,可以拿文件来跑跑,看看headHex是啥值就行了。

最后还有一个创建目录的辅助方法

1 /**

2 * 构建目录

3 * @param outputDir 输出目录

4 * @param subDir 子目录

5 */

6 private static void createDirectory(String outputDir, String subDir){

7 File file = new File(outputDir);

8 if(!(subDir == null || subDir.trim().equals(""))) {//子目录不为空

9 file = new File(outputDir + File.separator + subDir);

10 }

11 if(!file.exists()){

12 if(!file.getParentFile().exists()){

13 file.getParentFile().mkdirs();

14 }

15 file.mkdirs();

16 }

17 }

tar文件解压

接下来是正儿八经的正菜了。第一个来看怎么解压tar文件。好在解压tar文件的工具JDK自带了,下面看代码:

1 /**

2 * 解压缩tar文件

3 * @param file 压缩包文件

4 * @param targetPath 目标文件夹

5 * @param delete 解压后是否删除原压缩包文件

6 */

7 private static void decompressTar(File file, String targetPath, boolean delete){

8 FileInputStream fis = null;

9 OutputStream fos = null;

10 TarInputStream tarInputStream = null;

11 try {

12 fis = new FileInputStream(file);

13 tarInputStream = new TarInputStream(fis, 1024 * 2);

14 // 创建输出目录

15 createDirectory(targetPath, null);

16

17 TarEntry entry = null;

18 while(true){

19 entry = tarInputStream.getNextEntry();

20 if( entry == null){

21 break;

22 }

23 if(entry.isDirectory()){

24 createDirectory(targetPath, entry.getName()); // 创建子目录

25 }else{

26 fos = new FileOutputStream(new File(targetPath + File.separator + entry.getName()));

27 int count;

28 byte data[] = new byte[2048];

29 while ((count = tarInputStream.read(data)) != -1) {

30 fos.write(data, 0, count);

31 }

32 fos.flush();

33 }

34 }

35 } catch (IOException e) {

36 e.printStackTrace();

37 }finally {

38 try {

39 if(fis != null){

40 fis.close();

41 }

42 if(fos != null){

43 fos.close();

44 }

45 if(tarInputStream != null){

46 tarInputStream.close();

47 }

48 } catch (IOException e) {

49 e.printStackTrace();

50 }

51 }

52 }

有一点需要注意的是:方法参数传了一个是否需要删除原压缩包的参数,如果需要删除的话,必须!必须!必须!等到流关闭了之后才能删除,不然是删不掉的。也可以在该方法的调用者那里删,这样就可以不用传这个参数了。

bz2文件解压

解压bz2文件我这里是用的Apache的commons.compress工具来解压,先下载jar包:commons-compress-1.9.jar,(1.8的貌似有问题,我就换成了1.9)

1 /**

2 * 解压缩bz2文件

3 * @param file 压缩包文件

4 * @param targetPath 目标文件夹

5 * @param delete 解压后是否删除原压缩包文件

6 */

7 public static void decompressBZ2(File file, String targetPath, boolean delete){

8 FileInputStream fis = null;

9 OutputStream fos = null;

10 BZip2CompressorInputStream bis = null;

11 String suffix = ".bz2";

12 try {

13 fis = new FileInputStream(file);

14 bis = new BZip2CompressorInputStream(fis);

15 // 创建输出目录

16 createDirectory(targetPath, null);

17 File tempFile = new File(targetPath + File.separator + file.getName().replace(suffix, ""));

18 fos = new FileOutputStream(tempFile);

19

20 int count;

21 byte data[] = new byte[2048];

22 while ((count = bis.read(data)) != -1) {

23 fos.write(data, 0, count);

24 }

25 fos.flush();

26 } catch (IOException e) {

27 e.printStackTrace();

28 }finally {

29 try {

30 if(fis != null){

31 fis.close();

32 }

33 if(fos != null){

34 fos.close();

35 }

36 if(bis != null){

37 bis.close();

38 }

39 } catch (IOException e) {

40 e.printStackTrace();

41 }

42 }

43 }

tar.bz2文件解压

1 /**

2 * 解压缩tar.bz2文件

3 * @param file 压缩包文件

4 * @param targetPath 目标文件夹

5 * @param delete 解压后是否删除原压缩包文件

6 */

7 public static void decompressTarBz2(File file, String targetPath, boolean delete){

8 FileInputStream fis = null;

9 OutputStream fos = null;

10 BZip2CompressorInputStream bis = null;

11 TarInputStream tis = null;

12 try {

13 fis = new FileInputStream(file);

14 bis = new BZip2CompressorInputStream(fis);

15 tis = new TarInputStream(bis, 1024 * 2);

16 // 创建输出目录

17 createDirectory(targetPath, null);

18 TarEntry entry;

19 while((entry = tis.getNextEntry()) != null){

20 if(entry.isDirectory()){

21 createDirectory(targetPath, entry.getName()); // 创建子目录

22 }else{

23 fos = new FileOutputStream(new File(targetPath + File.separator + entry.getName()));

24 int count;

25 byte data[] = new byte[2048];

26 while ((count = tis.read(data)) != -1) {

27 fos.write(data, 0, count);

28 }

29 fos.flush();

30 }

31 }

32 } catch (IOException e) {

33 e.printStackTrace();

34 }finally {

35 try {

36 if(fis != null){

37 fis.close();

38 }

39 if(fos != null){

40 fos.close();

41 }

42 if(bis != null){

43 bis.close();

44 }

45 if(tis != null){

46 tis.close();

47 }

48 } catch (IOException e) {

49 e.printStackTrace();

50 }

51 }

52 }

tar.gz文件解压

1 /**

2 * 解压缩tar.gz文件

3 * @param file 压缩包文件

4 * @param targetPath 目标文件夹

5 * @param delete 解压后是否删除原压缩包文件

6 */

7 private static void decompressTarGz(File file, String targetPath, boolean delete){

8 FileInputStream fileInputStream = null;

9 BufferedInputStream bufferedInputStream = null;

10 GZIPInputStream gzipIn = null;

11 TarInputStream tarIn = null;

12 OutputStream out = null;

13 try {

14 fileInputStream = new FileInputStream(file);

15 bufferedInputStream = new BufferedInputStream(fileInputStream);

16 gzipIn = new GZIPInputStream(bufferedInputStream);

17 tarIn = new TarInputStream(gzipIn, 1024 * 2);

18

19 // 创建输出目录

20 createDirectory(targetPath, null);

21

22 TarEntry entry = null;

23 while((entry = tarIn.getNextEntry()) != null){

24 if(entry.isDirectory()){ // 是目录

25 createDirectory(targetPath, entry.getName()); // 创建子目录

26 }else{ // 是文件

27 File tempFIle = new File(targetPath + File.separator + entry.getName());

28 createDirectory(tempFIle.getParent() + File.separator, null);

29 out = new FileOutputStream(tempFIle);

30 int len =0;

31 byte[] b = new byte[2048];

32

33 while ((len = tarIn.read(b)) != -1){

34 out.write(b, 0, len);

35 }

36 out.flush();

37 }

38 }

39 } catch (IOException e) {

40 e.printStackTrace();

41 }finally {

42 try {

43 if(out != null){

44 out.close();

45 }

46 if(tarIn != null){

47 tarIn.close();

48 }

49 if(gzipIn != null){

50 gzipIn.close();

51 }

52 if(bufferedInputStream != null){

53 bufferedInputStream.close();

54 }

55 if(fileInputStream != null){

56 fileInputStream.close();

57 }

58 } catch (IOException e) {

59 e.printStackTrace();

60 }

61 }

62 }

gz文件解压

1 /**

2 * 解压缩gz文件

3 * @param file 压缩包文件

4 * @param targetPath 目标文件夹

5 * @param delete 解压后是否删除原压缩包文件

6 */

7 private static void decompressGz(File file, String targetPath, boolean delete){

8 FileInputStream fileInputStream = null;

9 GZIPInputStream gzipIn = null;

10 OutputStream out = null;

11 String suffix = ".gz";

12 try {

13 fileInputStream = new FileInputStream(file);

14 gzipIn = new GZIPInputStream(fileInputStream);

15 // 创建输出目录

16 createDirectory(targetPath, null);

17

18 File tempFile = new File(targetPath + File.separator + file.getName().replace(suffix, ""));

19 out = new FileOutputStream(tempFile);

20 int count;

21 byte data[] = new byte[2048];

22 while ((count = gzipIn.read(data)) != -1) {

23 out.write(data, 0, count);

24 }

25 out.flush();

26 } catch (IOException e) {

27 e.printStackTrace();

28 }finally {

29 try {

30 if(out != null){

31 out.close();

32 }

33 if(gzipIn != null){

34 gzipIn.close();

35 }

36 if(fileInputStream != null){

37 fileInputStream.close();

38 }

39 } catch (IOException e) {

40 e.printStackTrace();

41 }

42 }

43 }

7z文件解压

1 /**

2 * 解压缩7z文件

3 * @param file 压缩包文件

4 * @param targetPath 目标文件夹

5 * @param delete 解压后是否删除原压缩包文件

6 */

7 private static void decompress7Z(File file, String targetPath, boolean delete){

8 SevenZFile sevenZFile = null;

9 OutputStream outputStream = null;

10 try {

11 sevenZFile = new SevenZFile(file);

12 // 创建输出目录

13 createDirectory(targetPath, null);

14 SevenZArchiveEntry entry;

15

16 while((entry = sevenZFile.getNextEntry()) != null){

17 if(entry.isDirectory()){

18 createDirectory(targetPath, entry.getName()); // 创建子目录

19 }else{

20 outputStream = new FileOutputStream(new File(targetPath + File.separator + entry.getName()));

21 int len = 0;

22 byte[] b = new byte[2048];

23 while((len = sevenZFile.read(b)) != -1){

24 outputStream.write(b, 0, len);

25 }

26 outputStream.flush();

27 }

28 }

29 } catch (IOException e) {

30 e.printStackTrace();

31 }finally {

32 try {

33 if(sevenZFile != null){

34 sevenZFile.close();

35 }

36 if(outputStream != null){

37 outputStream.close();

38 }

39 } catch (IOException e) {

40 e.printStackTrace();

41 }

42 }

43 }

rar文件解压

先下载jar包:junrar-0.7.jar、xz-1.5.jar、commons-logging.jar

1 /**

2 * 解压缩RAR文件

3 * @param file 压缩包文件

4 * @param targetPath 目标文件夹

5 * @param delete 解压后是否删除原压缩包文件

6 */

7 private static void decompressRAR(File file, String targetPath, boolean delete){

8 Archive archive = null;

9 OutputStream outputStream = null;

10 try {

11 archive = new Archive(file);

12 FileHeader fileHeader;

13 // 创建输出目录

14 createDirectory(targetPath, null);

15 while( (fileHeader = archive.nextFileHeader()) != null){

16 if(fileHeader.isDirectory()){

17 createDirectory(targetPath, fileHeader.getFileNameString().trim()); // 创建子目录

18 }else{

19 outputStream = new FileOutputStream(new File(targetPath + File.separator + fileHeader.getFileNameString().trim()));

20 archive.extractFile(fileHeader, outputStream);

21 }

22 }

23 } catch (RarException | IOException e) {

24 e.printStackTrace();

25 }finally {

26 try {

27 if(archive != null){

28 archive.close();

29 }

30 if(outputStream != null){

31 outputStream.close();

32 }

33 } catch (IOException e) {

34 e.printStackTrace();

35 }

36 }

37 }

Copyright © 2088 2008世界杯_2026世界杯举办地 - mwllb.com All Rights Reserved.
友情链接