轉載自:https://blog.csdn.net/qq_28082757/article/details/78932756
這篇文章主要講解Java解壓的操作,后續會寫一篇關於壓縮的文章。
提醒:文章中有些片段看似代碼很多,其實去除trycatch、釋放資源真正有用的代碼沒幾句,解壓其實都很簡單,主要用心去觀察,都是依葫蘆畫瓢。
首先,先寫一個類似輔助的視圖類:
public enum FileType { // 未知 UNKNOWN, // 壓縮文件 ZIP, RAR, _7Z, TAR, GZ, TAR_GZ, BZ2, TAR_BZ2, // 位圖文件 BMP, PNG, JPG, JPEG, // 矢量圖文件 SVG, // 影音文件 AVI, MP4, MP3, AAR, OGG, WAV, WAVE }
這個類主要是用來將各種文件的類型集中管理,當然,不寫這個類也是可以的,可以直接用字符串去表示。
然后,我還寫了一個獲取文件真實類型的方法,為什么要寫這個方法呢?因為,我們是可以直接去修改文件的后綴的,這樣很危險!
本博客博主按:根據文件頭檢測文件類型+文件擴展名是比較嚴謹的辦法。
但是一些特殊情況可能是例外:例如千千靜聽,等軟件皮膚是zip文件,openoffice格式文件也是zip壓縮的,盡管他是xlsx格式的
/** * 獲取文件真實類型 * * @param file 要獲取類型的文件。 * @return 文件類型枚舉。 */ private static FileType getFileType(File file){ FileInputStream inputStream =null; try{ inputStream = new FileInputStream(file); byte[] head = new byte[4]; if (-1 == inputStream.read(head)) { return FileType.UNKNOWN; } int headHex = 0; for (byte b : head) { headHex <<= 8; headHex |= b; } switch (headHex) { case 0x504B0304: return FileType.ZIP; case 0x776f7264: return FileType.TAR; case -0x51: return FileType._7Z; case 0x425a6839: return FileType.BZ2; case -0x74f7f8: return FileType.GZ; case 0x52617221: return FileType.RAR; default: return FileType.UNKNOWN; } }catch (Exception e){ e.printStackTrace(); }finally { try { if(inputStream!=null){ inputStream.close(); } } catch (IOException e) { e.printStackTrace(); } } return FileType.UNKNOWN; }
這里是通過文件頭信息來判斷什么類型的。其他文件的頭文件信息,這里就不展示了。如果有需要,可以拿文件來跑跑,看看headHex是啥值就行了。
最后還有一個創建目錄的輔助方法:
/** * 構建目錄 * @param outputDir 輸出目錄 * @param subDir 子目錄 */ private static void createDirectory(String outputDir, String subDir){ File file = new File(outputDir); if(!(subDir == null || subDir.trim().equals(""))) {//子目錄不為空 file = new File(outputDir + File.separator + subDir); } if(!file.exists()){ if(!file.getParentFile().exists()){ file.getParentFile().mkdirs(); } file.mkdirs(); } }
tar文件解壓
接下來是正兒八經的正菜了。第一個來看怎么解壓tar文件。
好在解壓tar文件的工具JDK自帶了~下面看代碼:
/** * 解壓縮tar文件 * @param file 壓縮包文件 * @param targetPath 目標文件夾 * @param delete 解壓后是否刪除原壓縮包文件 */ private static void decompressTar(File file, String targetPath, boolean delete){ FileInputStream fis = null; OutputStream fos = null; TarInputStream tarInputStream = null; try { fis = new FileInputStream(file); tarInputStream = new TarInputStream(fis, 1024 * 2); // 創建輸出目錄 createDirectory(targetPath, null); TarEntry entry = null; while(true){ entry = tarInputStream.getNextEntry(); if( entry == null){ break; } if(entry.isDirectory()){ createDirectory(targetPath, entry.getName()); // 創建子目錄 }else{ fos = new FileOutputStream(new File(targetPath + File.separator + entry.getName())); int count; byte data[] = new byte[2048]; while ((count = tarInputStream.read(data)) != -1) { fos.write(data, 0, count); } fos.flush(); } } } catch (IOException e) { e.printStackTrace(); }finally { try { if(fis != null){ fis.close(); } if(fos != null){ fos.close(); } if(tarInputStream != null){ tarInputStream.close(); } } catch (IOException e) { e.printStackTrace(); } } }
有一點需要注意的是:方法參數傳了一個是否需要刪除原壓縮包的參數,如果需要刪除的話,必須必須必須等到流關閉了之后才能刪除,不然是刪不掉的。也可以在該方法的調用者那里刪,這樣就可以不用傳這個參數了。
bz2文件解壓
解壓bz2文件我這里是用的Apache的commons.compress工具來解壓,先下載jar包:commons-compress-1.9.jar,(1.8的貌似有問題,我就換成了1.9)
/** * 解壓縮bz2文件 * @param file 壓縮包文件 * @param targetPath 目標文件夾 * @param delete 解壓后是否刪除原壓縮包文件 */ public static void decompressBZ2(File file, String targetPath, boolean delete){ FileInputStream fis = null; OutputStream fos = null; BZip2CompressorInputStream bis = null; String suffix = ".bz2"; try { fis = new FileInputStream(file); bis = new BZip2CompressorInputStream(fis); // 創建輸出目錄 createDirectory(targetPath, null); File tempFile = new File(targetPath + File.separator + file.getName().replace(suffix, "")); fos = new FileOutputStream(tempFile); int count; byte data[] = new byte[2048]; while ((count = bis.read(data)) != -1) { fos.write(data, 0, count); } fos.flush(); } catch (IOException e) { e.printStackTrace(); }finally { try { if(fis != null){ fis.close(); } if(fos != null){ fos.close(); } if(bis != null){ bis.close(); } } catch (IOException e) { e.printStackTrace(); } } }
tar.bz2文件解壓
/** * 解壓縮tar.bz2文件 * @param file 壓縮包文件 * @param targetPath 目標文件夾 * @param delete 解壓后是否刪除原壓縮包文件 */ public static void decompressTarBz2(File file, String targetPath, boolean delete){ FileInputStream fis = null; OutputStream fos = null; BZip2CompressorInputStream bis = null; TarInputStream tis = null; try { fis = new FileInputStream(file); bis = new BZip2CompressorInputStream(fis); tis = new TarInputStream(bis, 1024 * 2); // 創建輸出目錄 createDirectory(targetPath, null); TarEntry entry; while((entry = tis.getNextEntry()) != null){ if(entry.isDirectory()){ createDirectory(targetPath, entry.getName()); // 創建子目錄 }else{ fos = new FileOutputStream(new File(targetPath + File.separator + entry.getName())); int count; byte data[] = new byte[2048]; while ((count = tis.read(data)) != -1) { fos.write(data, 0, count); } fos.flush(); } } } catch (IOException e) { e.printStackTrace(); }finally { try { if(fis != null){ fis.close(); } if(fos != null){ fos.close(); } if(bis != null){ bis.close(); } if(tis != null){ tis.close(); } } catch (IOException e) { e.printStackTrace(); } } }
tar.gz文件解壓
/** * 解壓縮tar.gz文件 * @param file 壓縮包文件 * @param targetPath 目標文件夾 * @param delete 解壓后是否刪除原壓縮包文件 */ private static void decompressTarGz(File file, String targetPath, boolean delete){ FileInputStream fileInputStream = null; BufferedInputStream bufferedInputStream = null; GZIPInputStream gzipIn = null; TarInputStream tarIn = null; OutputStream out = null; try { fileInputStream = new FileInputStream(file); bufferedInputStream = new BufferedInputStream(fileInputStream); gzipIn = new GZIPInputStream(bufferedInputStream); tarIn = new TarInputStream(gzipIn, 1024 * 2); // 創建輸出目錄 createDirectory(targetPath, null); TarEntry entry = null; while((entry = tarIn.getNextEntry()) != null){ if(entry.isDirectory()){ // 是目錄 createDirectory(targetPath, entry.getName()); // 創建子目錄 }else{ // 是文件 File tempFIle = new File(targetPath + File.separator + entry.getName()); createDirectory(tempFIle.getParent() + File.separator, null); out = new FileOutputStream(tempFIle); int len =0; byte[] b = new byte[2048]; while ((len = tarIn.read(b)) != -1){ out.write(b, 0, len); } out.flush(); } } } catch (IOException e) { e.printStackTrace(); }finally { try { if(out != null){ out.close(); } if(tarIn != null){ tarIn.close(); } if(gzipIn != null){ gzipIn.close(); } if(bufferedInputStream != null){ bufferedInputStream.close(); } if(fileInputStream != null){ fileInputStream.close(); } } catch (IOException e) { e.printStackTrace(); } } }
gz文件解壓
/** * 解壓縮gz文件 * @param file 壓縮包文件 * @param targetPath 目標文件夾 * @param delete 解壓后是否刪除原壓縮包文件 */ private static void decompressGz(File file, String targetPath, boolean delete){ FileInputStream fileInputStream = null; GZIPInputStream gzipIn = null; OutputStream out = null; String suffix = ".gz"; try { fileInputStream = new FileInputStream(file); gzipIn = new GZIPInputStream(fileInputStream); // 創建輸出目錄 createDirectory(targetPath, null); File tempFile = new File(targetPath + File.separator + file.getName().replace(suffix, "")); out = new FileOutputStream(tempFile); int count; byte data[] = new byte[2048]; while ((count = gzipIn.read(data)) != -1) { out.write(data, 0, count); } out.flush(); } catch (IOException e) { e.printStackTrace(); }finally { try { if(out != null){ out.close(); } if(gzipIn != null){ gzipIn.close(); } if(fileInputStream != null){ fileInputStream.close(); } } catch (IOException e) { e.printStackTrace(); } } }
7z文件解壓
/** * 解壓縮7z文件 * @param file 壓縮包文件 * @param targetPath 目標文件夾 * @param delete 解壓后是否刪除原壓縮包文件 */ private static void decompress7Z(File file, String targetPath, boolean delete){ SevenZFile sevenZFile = null; OutputStream outputStream = null; try { sevenZFile = new SevenZFile(file); // 創建輸出目錄 createDirectory(targetPath, null); SevenZArchiveEntry entry; while((entry = sevenZFile.getNextEntry()) != null){ if(entry.isDirectory()){ createDirectory(targetPath, entry.getName()); // 創建子目錄 }else{ outputStream = new FileOutputStream(new File(targetPath + File.separator + entry.getName())); int len = 0; byte[] b = new byte[2048]; while((len = sevenZFile.read(b)) != -1){ outputStream.write(b, 0, len); } outputStream.flush(); } } } catch (IOException e) { e.printStackTrace(); }finally { try { if(sevenZFile != null){ sevenZFile.close(); } if(outputStream != null){ outputStream.close(); } } catch (IOException e) { e.printStackTrace(); } } }
rar文件解壓
先下載jar包:junrar-0.7.jar、xz-1.5.jar、commons-logging.jar
/** * 解壓縮RAR文件 * @param file 壓縮包文件 * @param targetPath 目標文件夾 * @param delete 解壓后是否刪除原壓縮包文件 */ private static void decompressRAR(File file, String targetPath, boolean delete){ Archive archive = null; OutputStream outputStream = null; try { archive = new Archive(file); FileHeader fileHeader; // 創建輸出目錄 createDirectory(targetPath, null); while( (fileHeader = archive.nextFileHeader()) != null){ if(fileHeader.isDirectory()){ createDirectory(targetPath, fileHeader.getFileNameString().trim()); // 創建子目錄 }else{ outputStream = new FileOutputStream(new File(targetPath + File.separator + fileHeader.getFileNameString().trim())); archive.extractFile(fileHeader, outputStream); } } } catch (RarException | IOException e) { e.printStackTrace(); }finally { try { if(archive != null){ archive.close(); } if(outputStream != null){ outputStream.close(); } } catch (IOException e) { e.printStackTrace(); } } }