這篇文章主要講解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檔案
* @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檔案解壓
/**
* 解壓縮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();
}
}
}