今天項目中遇到zip檔案的壓縮與解壓問題。處理的是壓縮和解壓多級目錄的問題。
廢話不說把代碼先貼上。
/**
* 建立ZIP檔案
* @author 小馬
* @creaetime 2013年12月9日 下午4:30:37
* @param sourcePath 檔案或檔案夾路徑
* @param zipPath 生成的zip檔案存在路徑(包括檔案名)
*/
public boolean createZip(String sourcePath, String zipPath) {
FileOutputStream fos = null;
ZipOutputStream zos = null;
File file = null;
boolean result = false;
try {
fos = new FileOutputStream(zipPath);
zos = new ZipOutputStream(fos);
file = new File(sourcePath);
result = writeZip(file, "", zos);
}
catch (FileNotFoundException e) {
result = false;
}
finally {
try {
if ( zos != null ) {
zos.close();
}
// del(sourcePath);
}
catch (IOException e) {
result = false;
}
}
return result;
}
/**
* @author 小馬
* @creaetime 2013年12月9日 下午4:30:30
* @param file
* @param parentPath
* @param zos
*/
private boolean writeZip(File file, String parentPath, ZipOutputStream zos) {
boolean flag = true;
if ( file.exists() ) {
if ( file.isDirectory() ) {// 處理檔案夾
parentPath += file.getName() + File.separator;
File[] files = file.listFiles();
for (File f : files) {
writeZip(f, parentPath, zos);
}
}
else {
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
ZipEntry ze = new ZipEntry(parentPath + file.getName());
zos.putNextEntry(ze);
byte[] content = new byte[1024];
int len;
while ((len = fis.read(content)) != -1) {
zos.write(content, 0, len);
zos.flush();
}
}
catch (FileNotFoundException e) {
flag = false;
}
catch (IOException e) {
flag = false;
}
finally {
try {
if ( fis != null ) {
fis.close();
}
}
catch (IOException e) {
flag = false;
}
}
}
}
return flag;
}
以上是檔案的壓縮方法,需要用到java.util.zip.*這個包。但是處了解壓過程中一直遇到中文亂碼問題,就是當檔案後者目錄為中文的時候,程式要報異常。
最後在網上找到了解決的方法,代碼如下:
/**
* 解壓zip
* @author 小馬
* @creaetime 2013年12月11日 下午5:20:50
* @param path 要解壓檔案
* @param savepath 檔案解壓後儲存的目錄
*/
public static void unZip(String path, String savepath) {
int count = -1;
File file = null;
InputStream is = null;
FileOutputStream fos = null;
BufferedOutputStream bos = null;
//如果儲存目錄不存在則建立
if ( !new File(savepath).exists() ) {
new File(savepath).mkdir();
}
ZipFile zipFile = null;
try {
zipFile = new ZipFile(path, "gbk"); // 解決中文亂碼問題
Enumeration<?> entries = zipFile.getEntries();
while (entries.hasMoreElements()) {
byte buf[] = new byte[1024];
ZipEntry entry = (ZipEntry) entries.nextElement();
String filename = entry.getName();
boolean ismkdir = false;
if ( filename.lastIndexOf("/") != -1 ) { // 檢查此檔案是否帶有檔案夾
ismkdir = true;
}
filename = savepath + filename;
if ( entry.isDirectory() ) { // 如果是檔案夾先建立
file = new File(filename);
file.mkdirs();
continue;
}
file = new File(filename);
if ( !file.exists() ) { // 如果是目錄先建立
if ( ismkdir ) {
new File(filename.substring(0, filename.lastIndexOf("/"))).mkdirs(); // 目錄先建立
}
}
file.createNewFile(); // 建立檔案
is = zipFile.getInputStream(entry);
fos = new FileOutputStream(file);
bos = new BufferedOutputStream(fos, 1024);
while ((count = is.read(buf)) > -1) {
bos.write(buf, 0, count);
}
bos.flush();
bos.close();
fos.close();
is.close();
}
zipFile.close();
}
catch (IOException ioe) {
ioe.printStackTrace();
}
finally {
try {
if ( bos != null ) {
bos.close();
}
if ( fos != null ) {
fos.close();
}
if ( is != null ) {
is.close();
}
if ( zipFile != null ) {
zipFile.close();
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}
解壓方法,需要用com.springsource.org.apache.tools.ant.jar 這個包,問題解決。但是在解壓原始的zip沒有問題,在解壓自己壓縮的zip則報出找不到目錄的錯誤,經過不斷折騰,斷點調試,發現 原始的zip中 String filename = entry.getName(); filename路徑是以“/”隔開,而自己壓縮的zip中,filename的路徑是以“\”隔開,于是改成String filename = entry.getName().replace("\\", "/");問題就解決了。
發現壓縮後的檔案仍有亂碼,于是壓縮方法也用org.apache.tools.zip這個包。
上代碼:
/**
* 壓縮成zip
* @author 小馬
* @creaetime 2013年12月12日 上午11:39:58
* @param zipFilep 壓縮後的zip檔案名
* @param path 壓縮路徑
* @throws Exception
*/
public boolean createZip(String path, String zipFilep) {
System.out.println("備份檔案開始.....................");
File zipFile = new File(zipFilep);
boolean result = false;
ZipOutputStream out = null;
try {
if ( !zipFile.exists() ) {
zipFile.createNewFile();
}
out = new ZipOutputStream(new FileOutputStream(zipFile));
out.setEncoding("gbk");
write(out, path, "");
result = true;
}
catch (Exception e) {
result = false;
}finally{
if(out!=null){
try {
out.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
System.out.println("備份檔案結束.....................");
return result;
}
/**
* 寫壓縮流
* @author 小馬
* @creaetime 2013年12月12日 上午11:40:42
* @param out 壓縮輸出流
* @param path 壓縮路徑
* @param base 壓縮式的基礎目錄 預設為空
* @throws Exception
*/
private void write(ZipOutputStream out, String path, String base) throws Exception {
File file = new File(path);
if ( file.isDirectory() ) {// 檔案夾,遞歸
base = base.length() == 0 ? "" : base + File.separator;
File[] tempFiles = file.listFiles();
for (int i = 0; i < tempFiles.length; i++) {
write(out, tempFiles[i].getPath(), base + tempFiles[i].getName());
}
}
else {// 檔案,壓縮
byte[] buff = new byte[2048];
int bytesRead = -1;
ZipEntry entry = new ZipEntry(base);
out.putNextEntry(entry);
InputStream in = new BufferedInputStream(new FileInputStream(file));
while (-1 != (bytesRead = in.read(buff, 0, buff.length))) {
out.write(buff, 0, bytesRead);
}
in.close();
out.flush();
}
}