最近在自學javaWeb,先複習一下java,把還給老師的東西再找回來(知識如果不用很快就會忘記啊)。。
今天看到了zip壓縮,決定要整理一下。
java将有關zip壓縮的内容都封裝在java.util.zip寶中,用java實作zip壓縮,不用考慮壓縮算法,java已經将這些進行了封裝
實際上用java實作zip壓縮涉及的就是一個“輸入輸出流”的概念
用java實作一個檔案的zip壓縮,過程可以簡單地表示為:
當然具體實作要比這個複雜一點,比如要先像zip檔案中寫入目錄進入點。。如果要壓縮檔案夾中的内容要周遊檔案夾中的檔案和子檔案夾。
先給出源代碼,再解釋:
import java.io.*;
import java.util.*;
import java.util.zip.*;
class ZipCompress
{
private String zipFileName; // 目的地Zip檔案
private String sourceFileName; //源檔案(帶壓縮的檔案或檔案夾)
public ZipCompress(String zipFileName,String sourceFileName)
{
this.zipFileName=zipFileName;
this.sourceFileName=sourceFileName;
}
public void zip() throws Exception
{
//File zipFile = new File(zipFileName);
System.out.println("壓縮中...");
//建立zip輸出流
ZipOutputStream out = new ZipOutputStream( new FileOutputStream(zipFileName));
//建立緩沖輸出流
BufferedOutputStream bos = new BufferedOutputStream(out);
File sourceFile = new File(sourceFileName);
//調用函數
compress(out,bos,sourceFile,sourceFile.getName());
bos.close();
out.close();
System.out.println("壓縮完成");
}
public void compress(ZipOutputStream out,BufferedOutputStream bos,File sourceFile,String base) throws Exception
{
//如果路徑為目錄(檔案夾)
if(sourceFile.isDirectory())
{
//取出檔案夾中的檔案(或子檔案夾)
File[] flist = sourceFile.listFiles();
if(flist.length==0)//如果檔案夾為空,則隻需在目的地zip檔案中寫入一個目錄進入點
{
System.out.println(base+"/");
out.putNextEntry( new ZipEntry(base+"/") );
}
else//如果檔案夾不為空,則遞歸調用compress,檔案夾中的每一個檔案(或檔案夾)進行壓縮
{
for(int i=0;i<flist.length;i++)
{
compress(out,bos,flist[i],base+"/"+flist[i].getName());
}
}
}
else//如果不是目錄(檔案夾),即為檔案,則先寫入目錄進入點,之後将檔案寫入zip檔案中
{
out.putNextEntry( new ZipEntry(base) );
FileInputStream fos = new FileInputStream(sourceFile);
BufferedInputStream bis = new BufferedInputStream(fos);
int tag;
System.out.println(base);
//将源檔案寫入到zip檔案中
while((tag=bis.read())!=-1)
{
bos.write(tag);
}
bis.close();
fos.close();
}
}
}
public class TestZip
{
public static void main(String[] args)
{
ZipCompress zipCom = new ZipCompress("D:\\電影.zip","F:\\電影");
try
{
zipCom.zip();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
zip()方法中首先建立了ZipOutputStream(zip輸出流)之後調用compress()方法
在compress()方法中通過遞歸完成将檔案夾中的每個檔案的壓縮。
具體為:
首先判斷輸入的檔案是檔案夾還是檔案,如果是檔案,直接壓縮,如果是檔案夾則要遞歸調用compress()周遊壓縮檔案夾中的檔案。
如果是檔案,首先在zip檔案中寫入一個目錄進入點(所謂目錄進入點,個人了解就是源檔案在目标zip檔案中的路徑)
然後用檔案輸入流FileInputStream将源檔案讀入記憶體,在用ZipOutputStream(zip輸出流)将讀入記憶體的資料寫入到zip檔案中,這就完成了壓縮。(實際上就是輸入輸出流)
當檔案夾為空的時候,隻需寫入一個目錄進入點(要注意最後一定要加一個"\",表示一個目錄)。
運作結果為:
源檔案:
其中檔案夾1中含有兩個檔案,檔案夾2 為空。
壓縮後的檔案為:
前面提到的空檔案夾的目錄進入點一定要加"\",以表示一個檔案夾,而不是一個檔案,我們可以把程式中的"\"去掉,這時結果為:
可以看到本來是檔案夾的檔案夾2,程式設計了檔案。是以可以把目錄進入點就了解為,源檔案在zip檔案中對應的路徑,這個相對路徑應該與源檔案夾中的相對路徑一緻,當然也可以不一緻,比如我們在base前加入一個字元串"我愛",
out.putNextEntry( new ZipEntry("我愛"+base) );
結果為:
可以看到zip中的根目錄變成了“我愛電影”而不是原來的電影
水準有限。。。請多多指教。。。。