前言
這篇文章主要講解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 }
