壓縮文件或目錄
public static void zip(String src,String dest) throws IOException {
//定義壓縮輸出流
ZipOutputStream out = null;
try {
//傳入源文件
File fileOrDirectory= new File(src);
File outFile= new File(dest);
//傳入壓縮輸出流
//創建文件前幾級目錄
if (!outFile.exists()){
File parentfile=outFile.getParentFile();
if (!parentfile.exists()){
parentfile.mkdirs();
}
}
//可以通過createNewFile()函數這樣創建一個空的文件,也可以通過文件流的使用創建
out = new ZipOutputStream(new FileOutputStream(outFile));
//判斷是否是一個文件或目錄
//如果是文件則壓縮
if (fileOrDirectory.isFile()){
zipFileOrDirectory(out,fileOrDirectory, "");
} else {
//否則列出目錄中的所有文件遞歸進行壓縮
File[]entries = fileOrDirectory.listFiles();
for (int i= 0; i < entries.length;i++) {
zipFileOrDirectory(out,entries[i],fileOrDirectory.getName()+"/");//傳入最外層目錄名
}
}
}catch(IOException ex) {
ex.printStackTrace();
}finally{
if (out!= null){
try {
out.close();
}catch(IOException ex) {
ex.printStackTrace();
}
}
}
}
private static void zipFileOrDirectory(ZipOutputStream out, File fileOrDirectory, String curPath)throws IOException {
FileInputStream in = null;
try {
//判斷是否爲目錄
if (!fileOrDirectory.isDirectory()){
byte[] buffer= new byte[4096];
int bytes_read;
in= new FileInputStream(fileOrDirectory);//讀目錄中的子項
//歸檔壓縮目錄
ZipEntry entry = new ZipEntry(curPath + fileOrDirectory.getName());//壓縮到壓縮目錄中的文件名字
//getName() 方法返回的路徑名的名稱序列的最後一個名字,這意味着表示此抽象路徑名的文件或目錄的名稱被返回。
//將壓縮目錄寫到輸出流中
out.putNextEntry(entry);//out是帶有最初傳進的文件信息,一直添加子項歸檔目錄信息
while ((bytes_read= in.read(buffer))!= -1) {
out.write(buffer,0, bytes_read);
}
out.closeEntry();
} else {
//列出目錄中的所有文件
File[]entries = fileOrDirectory.listFiles();
for (int i= 0; i < entries.length;i++) {
//遞歸壓縮
zipFileOrDirectory(out,entries[i],curPath + fileOrDirectory.getName()+ "/");//第一次傳入的curPath是空字符串
}//目錄沒有後綴所以直接可以加"/"
}
}catch(IOException ex) {
ex.printStackTrace();
}finally{
if (in!= null){
try {
in.close();
}catch(IOException ex) {
ex.printStackTrace();
}
}
}
}
思路:
1.創建文件壓縮輸出流ZipOutputStream ,和文件讀入流FileInputStream
2.Zipoutputstream綁定一個目標目錄,用ZipEntry歸檔在目標目錄中添加輸出子項
ZipEntry entry = new ZipEntry(curPath + fileOrDirectory.getName());
out.putNextEntry(entry);
3.FileInputStream在每次讀入時綁定需要讀入的文件
壓縮時putNextEntry()對應解壓時的getNextEntry()
解壓文件或目錄##
public static void UnZipFolder(String FILE_PATH, String outPath) throws Exception{
File zipFile = new File(FILE_PATH);//FILE_PATH爲壓縮文件的路徑
ZipFile zf = new ZipFile(zipFile);
for(Enumeration<?> entries = zf.entries(); entries.hasMoreElements();){//遍歷壓縮文件中的所有歸檔過的文件
ZipEntry entry = ((ZipEntry)entries.nextElement());//默認爲-1,next->下標0的位置
InputStream is = zf.getInputStream(entry);
String str = outPath + File.separator + entry.getName();
str = new String(str.getBytes("8859_1"),"GB2312");//壓縮文件的編碼是8859_1,此處可將其轉換成指定的編碼
File desFile = new File(str);//其中單執行new file並不會在存儲中創建文件或文件夾
if(!desFile.exists()){
File fileParentDir = desFile.getParentFile();
if(!fileParentDir.exists()){
fileParentDir.mkdirs();//多級目錄同時創建 怕文件歸檔在很多級目錄下,或者文件需要在很多級未創建目錄下,mkdir不會創建父目錄,mkdirs會
}
desFile.createNewFile();//如果沒有父目錄將創建失敗
}
FileOutputStream out = new FileOutputStream(desFile);
byte buffer[] = new byte[1024*1024];
int readLength;
while((readLength = is.read(buffer)) > 0){
out.write(buffer, 0, readLength);
}
is.close();
out.close();
}
}
思路:
1.創建ZipFile對象
2.通過entry找到對應壓縮文件輸入流
InputStream is = zf.getInputStream(entry);
3.輸入輸出
爲了解決有時我們需要從解壓完的目錄中獲得某個指定文件的要求
/*
* 搜索對應文件從某目錄中
* */
//保存搜索到的文件
static File file;
public static File findFile(File fileorfolder,String requestFile){
file=null;//重置標識搜索文件的file爲空
searchFile(fileorfolder,requestFile);
return file;
}
private static void searchFile(File fileorfolder,String requestFile){
//是目錄
if(fileorfolder.isDirectory()){
File[] entries=fileorfolder.listFiles();
for(File enrtyfile:entries){
searchFile(enrtyfile,requestFile);
}
//是文件
}else {
//是傳入文件名對應文件
if (fileorfolder.getName().equals(requestFile)){//equals是比較字符串值是否相等
file=fileorfolder;
}
}
}
##踩過的坑
1.壓縮目錄後解壓,最外層目錄丟失 例:/360/3/1(目錄)2(目錄) 壓縮解壓完/360消失,只剩/3 解決:歸檔代碼出錯,沒有把歸檔信息帶上最外層目錄
2.(No such file or directory)異常,輸出時在new file的file路徑不存在(存在多級未創建目錄) 解決:
(1).desFile.createNewFile();
(2).FileOutputStream out = new FileOutputStream(desFile);
(1).(2)兩種方法都會創建文件,但如果沒有父目錄將創建失敗,父目錄可通過mkdirs創建,將遞歸創建
if (!outFile.exists()){
File parentfile=outFile.getParentFile();
if (!parentfile.exists()){
parentfile.mkdirs();
} }
使用到的一些類
ZipOutputStream :DeflaterOutputStream的一個子類,把數據壓縮成Zip文件格式。
ZipInputStream :InflaterInputStream的一個子類,能解壓縮Zip格式的數據
ZipEntry 類:表示 ZIP 文件條目
ZipFile 類:此類用於從 ZIP 文件讀取條目
ps:
1.壓縮時的ZipEntry 非常重要,是解壓時取得的歸檔信息
2.文件夾就算改成有後綴並不影響是文件夾:example->example.jpg還是文件夾
3.可以通過createNewFile()函數這樣創建一個空的文件,也可以通過文件流的使用創建
desFile.createNewFile();//如果沒有父目錄將創建失敗
FileOutputStream out = new FileOutputStream(desFile);//如果沒有父目錄將創建失敗,即No such file or directory