zip檔案結構
上面中的每一行都是一個條目,zip檔案就是由一個或者多個條目組成。
條目在Java中對應ZipEntry類
建立zip壓縮檔案
知道了zip檔案結構之後,大概就知道怎麼去建立一個zip壓縮檔案了。
之前,先了解下建立普通的檔案都是經過以下幾個步驟:
1、建立檔案輸出流FileOutputStream fout = new FileOutputStream(new File("XXX"));
2、往檔案輸出流中寫入檔案内容,fout.write(XXX);
3、關閉輸出流fout.close();
這樣,一個普通的建立就是生成了
既然zip壓縮檔案也是檔案,那麼它的建立也基本都差不多,隻是,zip檔案結構跟普通檔案有點差别,因為它裡面是由條目(ZipEntry)組成的。
是以建立zip壓縮檔案的步驟如下:
1、建立zip壓縮檔案輸出流
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(new File("XXX")));
2、建立zip檔案條目
ZipEntry entry = new ZipEntry(name)
備注:name指定條目的名稱,例如上圖顯示的client.cer,這裡name可以帶路徑,例如:a/b/c/test.txt,這樣就是建立a/b/c這個目錄。
3、将條目添加到zip檔案輸出流
zos.putNextEntry(entry);
4、建立被檔案的輸入流,讀取檔案内容,并寫入到zip壓縮檔案輸出流。這個時候,寫入的内容都屬于目前這個條目的。
FileInputStream in = new FileInputStream(new File("XXX"));
byte[]buffer = new byte[1024];
int len = 0;
while((len = in.read(buffer))!=-1){
zos.write(buffer ,0 ,len);
}
in.close();
5、關閉zip檔案輸出流
zos.close()
zip亂碼問題解決
使用Apache中的org.apache.tools.zip.ZipOutputStream類來替換Java自帶的ZipOutputStream類
FileOutputStream fout = new FileOutputStream("f:\\abc.zip");
ZipOutputStream out = new ZipOutputStream(fout);
out.setEncoding("utf-8"); //這條語句時必須的,否則,生成中文條目時,無法打開zip檔案或者出現亂碼
ZipEntry entry = new ZipEntry("測試檔案.txt");
out.putNextEntry(entry);
誤解區:
以前都是以為一個檔案或者目錄就對應zip檔案中的一個條目,其實并非一定是這樣的。解析如下:
zip檔案是以條目來組織,操作zip檔案都是基于條目來進行的,是以,每次往條目新增内容時,
得首先建立zip檔案條目,并将添加到zip檔案輸出,之後,zip輸出流,才認為之後寫入到輸出流中的
内容都是屬于這個條目,直到zip輸出流中新增新的條目。不過一般來正常來說,都是一個檔案或者目錄就對應zip檔案中的一個條目。
正常情況下,一個檔案或者目錄對應一個條目,如下圖:
但是也可以将a.txt、b.txt的内容都隻寫入的一個條目c.txt
生成的zip檔案結果圖:
這裡可以發現,隻要沒有重新往zip檔案輸出流中添加新的條目,那麼,所有的内容都是寫入目前條目中。
自己封裝的一個zip壓縮工具類
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class FilleUtils {
/**
* zip壓縮檔案,預設生成的壓縮檔案目錄與目前需要壓縮的檔案或者目錄同級
* @param filePath 需要壓縮的檔案或者目錄
* @return 傳回zip壓縮檔案路徑
*/
public static String zip(String filePath) throws Exception{
System.out.println("壓縮中...");
String zipFilePath = null;
File srcFile = new File(filePath);
//獲得zip檔案路徑
if(srcFile.isDirectory()){
zipFilePath = srcFile.getParent() + srcFile.getName() + ".zip";
}
else{
String zipFileName = "";
if(srcFile.getName().indexOf(".")>-1)
zipFileName = srcFile.getName().substring(0 ,srcFile.getName().lastIndexOf(".")) + ".zip";
else
zipFileName = srcFile.getName() + ".zip";
zipFilePath = srcFile.getParent() + zipFileName;
//開始進行壓縮
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFilePath));
BufferedOutputStream bo = new BufferedOutputStream(out);
zip(out, srcFile, srcFile.getName(), bo);
bo.close();
out.close();
System.out.println("壓縮完成");
return zipFilePath;
}
* zip壓縮檔案
* @param filePath
* @param zipFilePath
public static void zip(String filePath ,String zipFilePath) throws Exception{
//檢查壓縮檔案路徑是否存在,不存在則建立
File zipFile = new File(zipFilePath);
if(!zipFile.exists()){
zipFile.getParentFile().mkdirs();
//開始壓縮
out.close();
* 壓縮指定的多個檔案或者目錄
* @param filePathList
* @throws Exception
public static void zip(ArrayList<String> filePathList , String zipFilePath) throws Exception{
System.out.println("壓縮中...");
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFilePath));
BufferedOutputStream bo = new BufferedOutputStream(out);
if(filePathList==null || filePathList.size()==0){
throw new RuntimeException("沒有指定需要壓縮的檔案");
for(String filePath :filePathList){
File srcFile = new File(filePath);
zip(out, srcFile, srcFile.getName(), bo);
System.out.println("壓縮完成");
private static void zip(ZipOutputStream out , File srcFile ,String base ,BufferedOutputStream bo) throws Exception{
//如果需要壓縮的檔案是目錄,則進行遞歸壓縮處理
if(srcFile.isDirectory()){
File[] fileList = srcFile.listFiles();
//如果是空目錄,也需要将該目錄壓縮進去,注意,此時zipentry的name必須以“/"結束
if (fileList.length == 0) {
out.putNextEntry(new ZipEntry(base + "/")); // 建立zip壓縮進入點base
out.closeEntry();
}
for (int i = 0; i < fileList.length; i++) {
zip(out, fileList[i], base + "/" + fileList[i].getName(), bo); // 遞歸周遊子檔案夾
}
}
else{
out.putNextEntry(new ZipEntry(base)); // 建立zip壓縮進入點base
FileInputStream in = new FileInputStream(srcFile);
byte[]buffer = new byte[1024];
int len = 0;
while((len = in.read(buffer))!=-1){
out.write(buffer ,0 ,len);
}
in.close(); // 輸入流關閉
}
}
http://www.cnblogs.com/itmanxgl/p/84db9a95b5d84643580678994f6488b4.html