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     }
posted @ 2018-08-10 15:51  鲸落WhaleFall  阅读(10841)  评论(4编辑  收藏  举报