在java中專門有一個對zip檔案操作的包(java.util.zip),對zip檔案操作挺方便的,上次說寫一個zip檔案釋放程式,花了一天時間終於寫完了,起先想起來挺簡單的:原理就是將zip檔案中的檔案夾和檔案通過ZipInputStream和ZipEntry類一一得出,然後分別再對應目錄下建立檔案和檔案夾。可是實現起來就不是那麼回事了,其中有好多細節問題都不好解決,其中在調用ZipInputStream中的getNextEntry方法時如果zip檔案中包含中文路徑名或者檔案名稱就會拋出異常,所以這段程式難免會有許多錯誤和bug,甚至還有些思路上的問題,希望大家能多提意見。
其實java中對檔案的操作就是對輸入輸出資料流的運用和控制,這樣講有些範,但是如果你理解了流的運用就會覺得對檔案操作原來就是這樣呀!但是你千萬不要以為java的輸入輸出就這麼簡單,會用和用的好是兩碼事,就象同樣形容思想堅決,果斷和武斷就是兩個截然不同的描述,因此要想用好java的出入輸出還需要多多練習,多多思考。好了,說了那麼多都是些廢話,下面是程式源碼,希望對大家有用!
pcera
2005-7-2 17:44
/**
*類名:zipFileRelease
*說明:對zip檔案解壓,釋放在指定,目錄下
*介紹:主要的zip檔案釋放方法releaseHandle()
* 用ZipInputStream類和ZipEntry類將zip檔案的入口清單列舉出來,然後
* 根據使用者提供的輸出路徑和zip檔案的入口進行組合通過DataOutputStream
* 和File類進行檔案的建立和目錄的建立,建立檔案時的檔案資料是通過
* ZipInputStream類、ZipEntry類、InputStream類之間的套嵌組合獲得的。
*注意:如果zip檔案中包含中文路徑程式將會拋出異常
*日期:2005-7-1
*作者:Pcera
*/
import java.io.*;
import java.util.*;
import java.util.zip.*;
class zipFileRelease{
private String inFilePath;
private String releaseFilePath;
private String[] FileNameArray; //存放檔案名稱的數組
private ZipEntry entry;
//
private FileInputStream fileDataIn;
private FileOutputStream fileDataOut;
private ZipInputStream zipInFile;
private DataOutputStream writeData;
private DataInputStream readData;
//
private int zipFileCount = 0; //zip檔案中的檔案總數
private int zipPathCount = 0; //zip檔案中的路徑總數
/**
*初始化函數
*初始化zip檔案流、輸出檔案流以及其他變數的初始化
*/
public zipFileRelease(String inpath,String releasepath){
inFilePath = inpath;
releaseFilePath = releasepath;
}
/**
*初始化讀取檔案流函數
*參數:FileInputStream類
*傳回值:初始化成功返回0,否則返回-1
*/
protected long initInStream(ZipInputStream zipFileA){
try{
readData = new DataInputStream(zipFileA);
return 0;
}catch(Exception e){
e.printStackTrace();
return -1;
}
}
/**
*測試檔案路徑
*參數:zip檔案的路徑和要釋放的位置
*傳回值:是兩位整數,兩位元中的十位代表輸入路徑和輸出路徑(1輸入、2輸出)
* 各位元是代表絕對路徑還是相對路徑(1絕對、0相對)
* 返回-1表示路徑無效
protected long checkPath(String inPath,String outPath){
File infile = new File(inPath);
File infile = new File(outPath);
}
*/
/**
*初始化輸出檔案流
*參數:File類
*傳回值:初始化成功返回0,否則返回-1
*/
protected long initOutStream(String outFileA){
try{
fileDataOut = new FileOutputStream(outFileA);
writeData = new DataOutputStream(fileDataOut);
return 0;
}catch(IOException e){
e.printStackTrace();
return -1;
}
}
/**
*測試檔案是否存在方法
*參數:File類
*傳回值:如果檔案存在返迴文件大小,否則返回-1
*/
public long checkFile(File inFileA){
if (inFileA.exists()){
return 0;
}else{
return -1;
}
}
/**
*判斷檔案是否可以讀取方法
*參數:File類
*傳回值:如果可以讀取返回0,否則返回-1
*/
public long checkOpen(File inFileA){
if(inFileA.canRead()){
return inFileA.length();
}else{
return -1;
}
}
/**
*獲得zip檔案中的檔案夾和檔案總數
*參數:File類
*傳回值:如果正常獲得則返回總數,否則返回-1
*/
public long getFilFoldCount(String infileA){
try{
int fileCount = 0;
zipInFile = new ZipInputStream(
new FileInputStream(infileA));
while ((entry = zipInFile.getNextEntry()) != null){
if (entry.isDirectory()){
zipPathCount++;
}else{
zipFileCount++;
}
fileCount++;
}
return fileCount;
}catch(IOException e){
e.printStackTrace();
return -1;
}
}
/**
*讀取zip檔案清單函數
*參數:File類
*傳回值:檔案清單數組
*/
public String[] getFileList(String infileA){
try{
ZipInputStream AzipInFile = new ZipInputStream(
new FileInputStream(infileA));
//建立數組對象
FileNameArray = new String[(int)getFilFoldCount(infileA)];
//將檔案名稱清單傳入數組
int i = 0;
while ((entry = AzipInFile.getNextEntry()) != null){
FileNameArray[i++] = entry.getName();
}
return FileNameArray;
}catch(IOException e){
e.printStackTrace();
return null;
}
}
/**
*建立檔案函數
*參數:File類
*傳回值:如果建立成功返回0,否則返回-1
*/
public long writeFile(String outFileA,byte[] dataByte){
try{
if (initOutStream(outFileA) == 0){
writeData.write(dataByte);
fileDataOut.close();
return 0;
}else{
fileDataOut.close();
return -1;
}
}catch(IOException e){
e.printStackTrace();
return -1;
}
}
/**
*讀取檔案內容函數
*參數:File類
*傳回值:如果讀取成功則返回讀取資料的位元組數組,如果失敗則返回空值
*/
protected byte[]
readFile(ZipEntry entryA,ZipInputStream zipFileA){
try{
long entryFilelen;
if (initInStream(zipFileA) == 0){
if ((entryFilelen = entryA.getSize()) >= 0){
byte[] entryFileData = new byte[(int)entryFilelen];
readData.readFully(entryFileData,0,(int)entryFilelen);
return entryFileData;
}else{
return null;
}
}else{
return null;
}
}catch(IOException e){
e.printStackTrace();
return null;
}
}
/**
*建立目錄函式
*參數:要建立目錄的路徑
*傳回值:如果建立成功則返回0,否則返回-1
*/
public long createFolder(String dir){
File file = new File(dir);
if (file.mkdirs()) {
return 0;
}else{
return -1;
}
}
/**
*刪除檔案
*參數:要刪除的檔案
*傳回值:如果刪除成功則返回0,要刪除的檔案不存在返回-2
* 如果要刪除的是個路徑則返回-3,刪除失敗則返回-1
*/
public long deleteFile(String Apath) throws SecurityException {
File file = new File(Apath.trim());
//檔案或路徑不存在
if (!file.exists()){
return -2;
}
//要刪除的是個路徑
if (!file.isFile()){
return -3;
}
//刪除
if (file.delete()){
return 0;
}else{
return -1;
}
}
/**
*刪除目錄
*參數:要刪除的目錄
*傳回值:如果刪除成功則返回0,刪除失敗則返回-1
*/
public long deleteFolder(String Apath){
File file = new File(Apath);
//刪除
if (file.delete()){
return 0;
}else{
return -1;
}
}
/**
*判斷所要解壓的路徑是否存在同名檔案
*參數:解壓路徑
*傳回值:如果存在同名檔案返回-1,否則返回0
*/
public long checkPathExists(String AreleasePath){
File file = new File(AreleasePath);
if (!file.exists()){
return 0;
}else{
return -1;
}
}
/**
*刪除zip中的檔案
*參數:檔案清單數組,釋放路徑
*傳回值:如果刪除成功返回0,否則返回-1
*/
protected
long deleteReleaseZipFile(String[] listFilePath,String releasePath){
long arrayLen,flagReturn;
int k = 0;
String tempPath;
//存放zip檔案清單的路徑
String[] pathArray = new String[zipPathCount];
//刪除檔案
arrayLen = listFilePath.length;
for(int i=0;i<(int)arrayLen;i++){
tempPath = releasePath.replace('\\','/') + listFilePath[i];
flagReturn = deleteFile(tempPath);
if (flagReturn == -2){
//什麼都不作
}else if (flagReturn == -3){
pathArray[k++] = tempPath;
}else if (flagReturn == -1){
return -1;
}
}
//刪除路徑
for(k = k - 1;k>=0;k--){
flagReturn = deleteFolder(pathArray[k]);
if (flagReturn == -1) return -1;
}
return 0;
}
/**
*獲得zip檔案的最上層的檔案夾名稱
*參數:zip檔案路徑
*傳回值:檔案夾名稱,如果失敗則返回null
*/
public String getZipRoot(String infileA){
String rootName;
try{
FileInputStream tempfile = new FileInputStream(infileA);
ZipInputStream AzipInFile = new ZipInputStream(tempfile);
ZipEntry Aentry;
Aentry = AzipInFile.getNextEntry();
rootName = Aentry.getName();
tempfile.close();
AzipInFile.close();
return rootName;
}catch(IOException e){
e.printStackTrace();
return null;
}
}
/**
*釋放流,釋放佔用資源
*/
protected void closeStream() throws Exception{
fileDataIn.close();
fileDataOut.close();
zipInFile.close();
writeData.flush();
}
/**
*解壓函數
*對使用者的zip檔案路徑和解壓路徑進行判斷,是否存在和開啟
*在輸入解壓路徑時如果輸入"/"則在和zip檔案存放的統計目錄下進行解壓
*傳回值:0表示釋放成功
* -1 表示您所要解壓的檔案不存在、
* -2表示您所要解壓的檔案不能被開啟、
* -3您所要釋放的路徑不存在、
* -4您所建立檔案目錄失敗、
* -5寫入檔案失敗、
* -6表示所要釋放的檔案已經存在、
* -50表示檔案讀取異常
*/
public long releaseHandle() throws Exception{
File inFile = new File(inFilePath);
File outFile = new File(releaseFilePath);
String tempFile;
String zipPath;
String zipRootPath;
String tempPathParent; //存放釋放路徑
byte[] zipEntryFileData;
//作有效性判斷
if (checkFile(inFile) == -1) {
return -1;}
if (checkOpen(inFile) == -1) {
return -2;}
//不是解壓再目前的目錄下時對路徑作有效性檢驗
if (!releaseFilePath.equals("/")){
//解壓在使用者指定目錄下
if (checkFile(outFile) == -1) {
return -3;}
}
//獲得標準釋放路徑
if (!releaseFilePath.equals("/")) {
tempPathParent = releaseFilePath.replace('\\','/')+ "/";
}else{
tempPathParent = inFile.getParent().replace('\\','/')+ "/";
}
//獲得zip檔案中的入口清單
FileNameArray = getFileList(inFilePath);
//獲得zip檔案的最上層目錄
zipRootPath = getZipRoot(inFilePath);
//
fileDataIn = new FileInputStream(inFilePath);
zipInFile = new ZipInputStream(fileDataIn);
//判斷是否已經存在要釋放的檔案夾
if (checkPathExists(tempPathParent +
zipRootPath.substring(0,zipRootPath.lastIndexOf("/"))) == -1){
return -6;
}
//
try{
//建立檔案夾和檔案
int i = 0;
while ((entry = zipInFile.getNextEntry()) != null){
if (entry.isDirectory()){
//建立目錄
zipPath = tempPathParent + FileNameArray[i];
zipPath = zipPath.substring(0,zipPath.lastIndexOf("/"));
if (createFolder(zipPath) == -1){
closeStream();
deleteReleaseZipFile(FileNameArray,tempPathParent);
return -4;
}
}else{
//讀取檔案資料
zipEntryFileData = readFile(entry,zipInFile);
//向檔案寫資料
tempFile = tempPathParent + FileNameArray[i];
//寫入檔案
if (writeFile(tempFile,zipEntryFileData) == -1){
closeStream();
deleteReleaseZipFile(FileNameArray,tempPathParent);
return -5;
}
}
i++;
}
//釋放資源
closeStream();
return 0;
}catch(Exception e){
closeStream();
deleteReleaseZipFile(FileNameArray,tempPathParent);
e.printStackTrace();
return -50;
}
}
/**
*示範函數
*根據使用者輸入的路徑對檔案進行解壓
*/
public static void main(String args[]) throws Exception {
long flag; //返回標誌
String inPath,releasePath;
//獲得使用者輸入資訊
BufferedReader userInput = new BufferedReader(
new InputStreamReader(System.in));
System.out.println("請輸入zip檔案路徑:");
inPath = userInput.readLine();
System.out.println("請輸入儲存路徑:");
releasePath = userInput.readLine();
userInput.close();
//執行解壓縮
zipFileRelease pceraZip = new zipFileRelease(inPath,releasePath);
flag = pceraZip.releaseHandle();
//出錯資訊列印
if (flag == 0) System.out.println("釋放成功!!!");
if (flag == -1) System.out.println("您所要解壓的檔案不存在!");
if (flag == -2) System.out.println("您所要解壓的檔案不能被開啟!");
if (flag == -3) System.out.println("您所要釋放的路徑不存在!");
if (flag == -4) System.out.println("您所建立檔案目錄失敗!");
if (flag == -5) System.out.println("寫入檔案失敗!");
if (flag == -6) System.out.println("檔案已經存在!");
if (flag == -50) System.out.println("檔案讀取異常!");
}
}