Android zip文件壓縮解壓
Android項目中需要將一些信息進行收集再進行壓縮,最後將壓縮文件上傳到服務器中,以下代碼實現此功能,並支持中文文件名
package com.example.androidzip.tools;
import java.io.File;
import java.util.ArrayList;
import java.util.LinkedList;
/**
* 文件夾遍歷
* @author miaowei
*
*/
public class DirTraversal {
//no recursion
public static LinkedList<File> listLinkedFiles(String strPath) {
LinkedList<File> list = new LinkedList<File>();
File dir = new File(strPath);
File file[] = dir.listFiles();
for (int i = 0; i < file.length; i++) {
/*if (file[i].isDirectory()){
list.add(file[i]);
}else{
System.out.println(file[i].getAbsolutePath());
}*/
list.add(file[i]);
}
/*File tmp;
while (!list.isEmpty()) {
tmp = (File) list.removeFirst();
if (tmp.isDirectory()) {
file = tmp.listFiles();
if (file == null)
continue;
for (int i = 0; i < file.length; i++) {
if (file[i].isDirectory())
list.add(file[i]);
else
System.out.println(file[i].getAbsolutePath());
}
} else {
System.out.println(tmp.getAbsolutePath());
}
}*/
return list;
}
//recursion
public static ArrayList<File> listFiles(String strPath) {
return refreshFileList(strPath);
}
public static ArrayList<File> refreshFileList(String strPath) {
ArrayList<File> filelist = new ArrayList<File>();
File dir = new File(strPath);
File[] files = dir.listFiles();
if (files == null)
return null;
for (int i = 0; i < files.length; i++) {
if (files[i].isDirectory()) {
refreshFileList(files[i].getAbsolutePath());
} else {
if(files[i].getName().toLowerCase().endsWith("zip")){
filelist.add(files[i]);
}
}
}
return filelist;
}
public static ArrayList<File> arrayListFiles(String strPath){
ArrayList<File> filelist = new ArrayList<File>();
File dir = new File(strPath);
File[] files = dir.listFiles();
for (int i = 0; i < files.length; i++) {
filelist.add(files[i].getAbsoluteFile());
}
return filelist;
}
//-----4.0讀取文件的報 open failed: ENOENT (No such file or directory)
/**
* 1\可先創建文件的路徑
* @param filePath
*/
public static void makeRootDirectory(String filePath) {
File file = null;
try {
file = new File(filePath);
if (!file.exists()) {
file.mkdir();
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 2\然後在創建文件名就不會在報該錯誤
* @param filePath
* @param fileName
* @return
*/
public static File getFilePath(String filePath, String fileName) {
File file = null;
makeRootDirectory(filePath);
try {
file = new File(filePath + fileName);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return file;
}
}
package com.example.androidzip.tools;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
/**
* Java utils 實現的Zip工具
* @author miaowei
*
*/
public class ZipUtils {
private static final int BUFF_SIZE = 1024 * 1024; // 1M Byte
/**
* 批量壓縮文件(夾)
*
* @param resFileList 要壓縮的文件(夾)列表
* @param zipFile 生成的壓縮文件
* @throws IOException 當壓縮過程出錯時拋出
*/
public static void zipFiles(Collection<File> resFileList, File zipFile) throws IOException {
ZipOutputStream zipout = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile), BUFF_SIZE));
for (File resFile : resFileList) {
zipFile(resFile, zipout, "");
}
zipout.close();
}
/**
* 批量壓縮文件(夾)
*
* @param resFileList 要壓縮的文件(夾)列表
* @param zipFile 生成的壓縮文件
* @param comment 壓縮文件的註釋
* @throws IOException 當壓縮過程出錯時拋出
*/
public static void zipFiles(Collection<File> resFileList, File zipFile, String comment)
throws IOException {
ZipOutputStream zipout = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(
zipFile), BUFF_SIZE));
for (File resFile : resFileList) {
zipFile(resFile, zipout, "");
}
zipout.setComment(comment);
zipout.close();
}
/**
* 解壓縮一個文件
*
* @param zipFile 壓縮文件
* @param folderPath 解壓縮的目標目錄
* @throws IOException 當解壓縮過程出錯時拋出
*/
public static void upZipFile(File zipFile, String folderPath) throws ZipException, IOException {
File desDir = new File(folderPath);
if (!desDir.exists()) {
desDir.mkdirs();
}
ZipFile zf = new ZipFile(zipFile);
for (Enumeration<?> entries = zf.entries(); entries.hasMoreElements();) {
ZipEntry entry = ((ZipEntry)entries.nextElement());
if (entry.isDirectory()) {
continue;
}
InputStream in = zf.getInputStream(entry);
String str = folderPath + File.separator + entry.getName();
str = new String(str.getBytes(), "utf-8");
File desFile = new File(str);
if (!desFile.exists()) {
File fileParentDir = desFile.getParentFile();
if (!fileParentDir.exists()) {
fileParentDir.mkdirs();
}
desFile.createNewFile();
}
OutputStream out = new FileOutputStream(desFile);
byte buffer[] = new byte[BUFF_SIZE];
int realLength;
while ((realLength = in.read(buffer)) > 0) {
out.write(buffer, 0, realLength);
}
in.close();
out.close();
}
}
/**
* 解壓文件名包含傳入文字的文件
*
* @param zipFile 壓縮文件
* @param folderPath 目標文件夾
* @param nameContains 傳入的文件匹配名
* @throws ZipException 壓縮格式有誤時拋出
* @throws IOException IO錯誤時拋出
*/
public static ArrayList<File> upZipSelectedFile(File zipFile, String folderPath,
String nameContains) throws ZipException, IOException {
ArrayList<File> fileList = new ArrayList<File>();
File desDir = new File(folderPath);
if (!desDir.exists()) {
desDir.mkdir();
}
ZipFile zf = new ZipFile(zipFile);
for (Enumeration<?> entries = zf.entries(); entries.hasMoreElements();) {
ZipEntry entry = ((ZipEntry)entries.nextElement());
if (entry.getName().contains(nameContains)) {
InputStream in = zf.getInputStream(entry);
String str = folderPath + File.separator + entry.getName();
str = new String(str.getBytes("utf-8"), "gbk");
// str.getBytes("GB2312"),"8859_1" 輸出
// str.getBytes("8859_1"),"GB2312" 輸入
File desFile = new File(str);
if (!desFile.exists()) {
File fileParentDir = desFile.getParentFile();
if (!fileParentDir.exists()) {
fileParentDir.mkdirs();
}
desFile.createNewFile();
}
OutputStream out = new FileOutputStream(desFile);
byte buffer[] = new byte[BUFF_SIZE];
int realLength;
while ((realLength = in.read(buffer)) > 0) {
out.write(buffer, 0, realLength);
}
in.close();
out.close();
fileList.add(desFile);
}
}
return fileList;
}
/**
* 獲得壓縮文件內文件列表
*
* @param zipFile 壓縮文件
* @return 壓縮文件內文件名稱
* @throws ZipException 壓縮文件格式有誤時拋出
* @throws IOException 當解壓縮過程出錯時拋出
*/
public static ArrayList<String> getEntriesNames(File zipFile) throws ZipException, IOException {
ArrayList<String> entryNames = new ArrayList<String>();
Enumeration<?> entries = getEntriesEnumeration(zipFile);
while (entries.hasMoreElements()) {
ZipEntry entry = ((ZipEntry)entries.nextElement());
entryNames.add(new String(getEntryName(entry).getBytes("GB2312"), "8859_1"));
}
return entryNames;
}
/**
* 獲得壓縮文件內壓縮文件對象以取得其屬性
*
* @param zipFile 壓縮文件
* @return 返回一個壓縮文件列表
* @throws ZipException 壓縮文件格式有誤時拋出
* @throws IOException IO操作有誤時拋出
*/
public static Enumeration<?> getEntriesEnumeration(File zipFile) throws ZipException,
IOException {
ZipFile zf = new ZipFile(zipFile);
return zf.entries();
}
/**
* 取得壓縮文件對象的註釋
*
* @param entry 壓縮文件對象
* @return 壓縮文件對象的註釋
* @throws UnsupportedEncodingException
*/
public static String getEntryComment(ZipEntry entry) throws UnsupportedEncodingException {
return new String(entry.getComment().getBytes("GB2312"), "8859_1");
}
/**
* 取得壓縮文件對象的名稱
*
* @param entry 壓縮文件對象
* @return 壓縮文件對象的名稱
* @throws UnsupportedEncodingException
*/
public static String getEntryName(ZipEntry entry) throws UnsupportedEncodingException {
return new String(entry.getName().getBytes("GB2312"), "8859_1");
}
/**
* 壓縮文件
*
* @param resFile 需要壓縮的文件(夾)
* @param zipout 壓縮的目的文件
* @param rootpath 壓縮的文件路徑
* @throws FileNotFoundException 找不到文件時拋出
* @throws IOException 當壓縮過程出錯時拋出
*/
private static void zipFile(File resFile, ZipOutputStream zipout, String rootpath)
throws FileNotFoundException, IOException {
rootpath = rootpath + (rootpath.trim().length() == 0 ? "" : File.separator)
+ resFile.getName();
rootpath = new String(rootpath.getBytes(), "utf-8");
if (resFile.isDirectory()) {
File[] fileList = resFile.listFiles();
for (File file : fileList) {
zipFile(file, zipout, rootpath);
}
} else {
byte buffer[] = new byte[BUFF_SIZE];
BufferedInputStream in = new BufferedInputStream(new FileInputStream(resFile),
BUFF_SIZE);
zipout.putNextEntry(new ZipEntry(rootpath));
int realLength;
while ((realLength = in.read(buffer)) != -1) {
zipout.write(buffer, 0, realLength);
}
in.close();
zipout.flush();
zipout.closeEntry();
}
}
//第二種實現
public static void zip(String src, String dest) throws IOException {
// 提供了一個數據項壓縮成一個ZIP歸檔輸出流
ZipOutputStream out = null;
try {
//DirTraversal.makeRootDirectory(dest);
//File outFile = DirTraversal.getFilePath(dest,"cache.zip");
File outFile = new File(dest);// 源文件或者目錄
File fileOrDirectory = new File(src);// 壓縮文件路徑
out = new ZipOutputStream(new FileOutputStream(outFile));
// 如果此文件是一個文件,否則爲false。
if (fileOrDirectory.isFile()) {
zipFileOrDirectory(out, fileOrDirectory, "");
} else {
// 返回一個文件或空陣列。
File[] entries = fileOrDirectory.listFiles();
for (int i = 0; i < entries.length; i++) {
// 遞歸壓縮,更新curPaths
zipFileOrDirectory(out, entries[i], "");
}
}
} 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 {
// 如果此文件是一個目錄,否則返回false。
if (!fileOrDirectory.isDirectory()) {
// 壓縮文件
byte[] buffer = new byte[4096];
int bytes_read;
in = new FileInputStream(fileOrDirectory);
// 實例代表一個條目內的ZIP歸檔
ZipEntry entry = new ZipEntry(curPath
+ fileOrDirectory.getName());
// 條目的信息寫入底層流
out.putNextEntry(entry);
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++) {
// 遞歸壓縮,更新curPaths
zipFileOrDirectory(out, entries[i], curPath
+ fileOrDirectory.getName() + "/");
}
}
} catch (IOException ex) {
ex.printStackTrace();
// throw ex;
} finally {
if (in != null) {
try {
in.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
@SuppressWarnings("unchecked")
public static void unzip(String zipFileName, String outputDirectory)
throws IOException {
ZipFile zipFile = null;
try {
zipFile = new ZipFile(zipFileName);
Enumeration e = zipFile.entries();
ZipEntry zipEntry = null;
File dest = new File(outputDirectory);
dest.mkdirs();
while (e.hasMoreElements()) {
zipEntry = (ZipEntry) e.nextElement();
String entryName = zipEntry.getName();
InputStream in = null;
FileOutputStream out = null;
try {
if (zipEntry.isDirectory()) {
String name = zipEntry.getName();
name = name.substring(0, name.length() - 1);
File f = new File(outputDirectory + File.separator
+ name);
f.mkdirs();
} else {
int index = entryName.lastIndexOf("\\");
if (index != -1) {
File df = new File(outputDirectory + File.separator
+ entryName.substring(0, index));
df.mkdirs();
}
index = entryName.lastIndexOf("/");
if (index != -1) {
File df = new File(outputDirectory + File.separator
+ entryName.substring(0, index));
df.mkdirs();
}
File f = new File(outputDirectory + File.separator
+ zipEntry.getName());
// f.createNewFile();
in = zipFile.getInputStream(zipEntry);
out = new FileOutputStream(f);
int c;
byte[] by = new byte[1024];
while ((c = in.read(by)) != -1) {
out.write(by, 0, c);
}
out.flush();
}
} catch (IOException ex) {
ex.printStackTrace();
throw new IOException("解壓失敗:" + ex.toString());
} finally {
if (in != null) {
try {
in.close();
} catch (IOException ex) {
}
}
if (out != null) {
try {
out.close();
} catch (IOException ex) {
}
}
}
}
} catch (IOException ex) {
ex.printStackTrace();
throw new IOException("解壓失敗:" + ex.toString());
} finally {
if (zipFile != null) {
try {
zipFile.close();
} catch (IOException ex) {
}
}
}
}
}
package com.example.androidzip;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.LinkedList;
import java.util.zip.ZipException;
import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import com.example.androidzip.tools.DirTraversal;
import com.example.androidzip.tools.ZipUtils;
/**
* Android zip文件壓縮解壓縮
* @author miaowei
*
*/
public class MainActivity extends Activity {
/**
* 壓縮
*/
private Button btn_zip;
/**
* 解壓
*/
private Button btn_unzip;
String pathString = Environment.getExternalStorageDirectory().getAbsolutePath();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn_unzip = (Button)findViewById(R.id.btn_unzip);
btn_zip = (Button)findViewById(R.id.btn_zip);
btn_zip.setOnClickListener(onClickListener);
btn_unzip.setOnClickListener(onClickListener);
}
private OnClickListener onClickListener = new OnClickListener(){
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_zip:
try {
//測試數據,注意更換目錄
LinkedList<File> files = DirTraversal.listLinkedFiles(pathString+"/Android/data/com.mapbar.info.collection/files/cache");
File file = DirTraversal.getFilePath(pathString+"/Android/data/com.mapbar.info.collection/files/", "cache.zip");
ZipUtils.zipFiles(files, file);
//第二種實現
//ZipUtils.zip(pathString+"/Android/data/com.mapbar.info.collection/files/cache", pathString+"/Android/data/com.mapbar.info.collection/files/cache.zip");
//ZipUtils.unzip(pathString+"/Android/data/com.mapbar.info.collection/files/cache.zip", pathString+"/Android/data/com.mapbar.info.collection/files/cache");
} catch (IOException e) {
e.printStackTrace();
}
break;
case R.id.btn_unzip:
File file = DirTraversal.getFilePath(pathString+"/Android/data/com.mapbar.info.collection/files/", "cache.zip");
try {
ZipUtils.upZipFile(file, pathString+"/Android/data/com.mapbar.info.collection/files/cachezip");
} catch (ZipException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
break;
default:
break;
}
}
};
}
以下爲處理亂碼轉換字符串的編碼
/**
* 轉換字符串的編碼
*/
public class ChangeCharset {
/** 7位ASCII字符,也叫作ISO646-US、Unicode字符集的基本拉丁塊 */
public static final String US_ASCII = "US-ASCII";
/** ISO 拉丁字母表 No.1,也叫作 ISO-LATIN-1 */
public static final String ISO_8859_1 = "ISO-8859-1";
/** 8 位 UCS 轉換格式 */
public static final String UTF_8 = "UTF-8";
/** 16 位 UCS 轉換格式,Big Endian(最低地址存放高位字節)字節順序 */
public static final String UTF_16BE = "UTF-16BE";
/** 16 位 UCS 轉換格式,Little-endian(最高地址存放低位字節)字節順序 */
public static final String UTF_16LE = "UTF-16LE";
/** 16 位 UCS 轉換格式,字節順序由可選的字節順序標記來標識 */
public static final String UTF_16 = "UTF-16";
/** 中文超大字符集 */
public static final String GBK = "GBK";
/**
* 將字符編碼轉換成US-ASCII碼
*/
public String toASCII(String str) throws UnsupportedEncodingException {
return this.changeCharset(str, US_ASCII);
}
/**
* 將字符編碼轉換成ISO-8859-1碼
*/
public String toISO_8859_1(String str) throws UnsupportedEncodingException {
return this.changeCharset(str, ISO_8859_1);
}
/**
* 將字符編碼轉換成UTF-8碼
*/
public String toUTF_8(String str) throws UnsupportedEncodingException {
return this.changeCharset(str, UTF_8);
}
/**
* 將字符編碼轉換成UTF-16BE碼
*/
public String toUTF_16BE(String str) throws UnsupportedEncodingException {
return this.changeCharset(str, UTF_16BE);
}
/**
* 將字符編碼轉換成UTF-16LE碼
*/
public String toUTF_16LE(String str) throws UnsupportedEncodingException {
return this.changeCharset(str, UTF_16LE);
}
/**
* 將字符編碼轉換成UTF-16碼
*/
public String toUTF_16(String str) throws UnsupportedEncodingException {
return this.changeCharset(str, UTF_16);
}
/**
* 將字符編碼轉換成GBK碼
*/
public String toGBK(String str) throws UnsupportedEncodingException {
return this.changeCharset(str, GBK);
}
/**
* 字符串編碼轉換的實現方法
* @param str 待轉換編碼的字符串
* @param newCharset 目標編碼
* @return
* @throws UnsupportedEncodingException
*/
public String changeCharset(String str, String newCharset)
throws UnsupportedEncodingException {
if (str != null) {
//用默認字符編碼解碼字符串。
byte[] bs = str.getBytes();
//用新的字符編碼生成字符串
return new String(bs, newCharset);
}
return null;
}
/**
* 字符串編碼轉換的實現方法
* @param str 待轉換編碼的字符串
* @param oldCharset 原編碼
* @param newCharset 目標編碼
* @return
* @throws UnsupportedEncodingException
*/
public String changeCharset(String str, String oldCharset, String newCharset)
throws UnsupportedEncodingException {
if (str != null) {
//用舊的字符編碼解碼字符串。解碼可能會出現異常。
byte[] bs = str.getBytes(oldCharset);
//用新的字符編碼生成字符串
return new String(bs, newCharset);
}
return null;
}
public static void main(String[] args) throws UnsupportedEncodingException {
ChangeCharset test = new ChangeCharset();
String str = "This is a 中文的 String!";
System.out.println("str: " + str);
String gbk = test.toGBK(str);
System.out.println("轉換成GBK碼: " + gbk);
System.out.println();
String ascii = test.toASCII(str);
System.out.println("轉換成US-ASCII碼: " + ascii);
gbk = test.changeCharset(ascii,ChangeCharset.US_ASCII, ChangeCharset.GBK);
System.out.println("再把ASCII碼的字符串轉換成GBK碼: " + gbk);
System.out.println();
String iso88591 = test.toISO_8859_1(str);
System.out.println("轉換成ISO-8859-1碼: " + iso88591);
gbk = test.changeCharset(iso88591,ChangeCharset.ISO_8859_1, ChangeCharset.GBK);
System.out.println("再把ISO-8859-1碼的字符串轉換成GBK碼: " + gbk);
System.out.println();
String utf8 = test.toUTF_8(str);
System.out.println("轉換成UTF-8碼: " + utf8);
gbk = test.changeCharset(utf8,ChangeCharset.UTF_8, ChangeCharset.GBK);
System.out.println("再把UTF-8碼的字符串轉換成GBK碼: " + gbk);
System.out.println();
String utf16be = test.toUTF_16BE(str);
System.out.println("轉換成UTF-16BE碼:" + utf16be);
gbk = test.changeCharset(utf16be,ChangeCharset.UTF_16BE, ChangeCharset.GBK);
System.out.println("再把UTF-16BE碼的字符串轉換成GBK碼: " + gbk);
System.out.println();
String utf16le = test.toUTF_16LE(str);
System.out.println("轉換成UTF-16LE碼:" + utf16le);
gbk = test.changeCharset(utf16le,ChangeCharset.UTF_16LE, ChangeCharset.GBK);
System.out.println("再把UTF-16LE碼的字符串轉換成GBK碼: " + gbk);
System.out.println();
String utf16 = test.toUTF_16(str);
System.out.println("轉換成UTF-16碼:" + utf16);
gbk = test.changeCharset(utf16,ChangeCharset.UTF_16LE, ChangeCharset.GBK);
System.out.println("再把UTF-16碼的字符串轉換成GBK碼: " + gbk);
String s = new String("中文".getBytes("UTF-8"),"UTF-8");
System.out.println(s);
}
}
附件中有源碼供參考