Android zip文件壓縮與解壓
Android開發中偶爾需要用到zip文件的壓縮與解壓,正好公司項目需要用到,趁此機會特意總結了下,分享給大家,也是對我學習Android的記錄。
zip壓縮
Android中的zip壓縮主要用到兩個類:ZipEntry,ZipOutputStream,ZipEntry類用於保存一些被壓縮文件的信息,如文件名、修改時間等等,部分源碼如下:
class ZipEntry implements ZipConstants, Cloneable {
String name; // entry name
long time = -1; // modification time (in DOS time)
long crc = -1; // crc-32 of entry data
long size = -1; // uncompressed size of entry data
long csize = -1; // compressed size of entry data
int method = -1; // compression method
int flag = 0; // general purpose flag
byte[] extra; // optional extra field data for entry
String comment; // optional comment string for entry
// Android-changed: Add dataOffset for internal use.
long dataOffset;
而ZipOutputStream是目標zip文件的輸出流。zip壓縮一共分爲三步:
- 獲取相應的ZipOutputStream;
- 判斷是否是文件夾
(1)是:遞歸;
(2)否:根據文件路徑、文件名等獲取相應的ZipEntry,然後將該文件寫入ZipOutputStream;
-
關閉相應的輸出流;
/** * 壓縮文件 * @param srcFile 待壓縮的源文件 * @param rootPath 源文件的根路徑 * @param zos Zip輸出流 * @param comment 備註 * @return 壓縮成功返回true * @throws IOException */ private static boolean zipFile(final File srcFile,String rootPath,final ZipOutputStream zos,final String comment) throws IOException { rootPath = rootPath + (isSpace(rootPath) ? "" : File.separator) + srcFile.getName(); if (srcFile.isDirectory()) { File[] fileList = srcFile.listFiles(); if (fileList == null || fileList.length <= 0) { ZipEntry entry = new ZipEntry(rootPath + '/'); entry.setComment(comment); zos.putNextEntry(entry); zos.closeEntry(); } else { for (File file : fileList) { if (!zipFile(file, rootPath, zos, comment)) return false; } } } else { InputStream is = null; try { is = new BufferedInputStream(new FileInputStream(srcFile)); ZipEntry entry = new ZipEntry(rootPath); entry.setComment(comment); zos.putNextEntry(entry); byte buffer[] = new byte[BUFFER_LEN]; int len; while ((len = is.read(buffer, 0, BUFFER_LEN)) != -1) { zos.write(buffer, 0, len); } zos.closeEntry(); } finally { CloseUtils.closeIO(is); } } return true; }
zip解壓
/**
* Unzip the file by keyword.
*
* @param zipFile The ZIP file.
* @param destDir The destination directory.
* @param keyword The keyboard.
* @return the unzipped files
* @throws IOException if unzip unsuccessfully
*/
public static List<File> unzipFileByKeyword(final File zipFile,final File destDir,final String keyword) throws IOException {
if (zipFile == null || destDir == null) return null;
List<File> files = new ArrayList<>();
ZipFile zip = new ZipFile(zipFile);
Enumeration<?> entries = zip.entries();
try {
if (isSpace(keyword)) {
while (entries.hasMoreElements()) {
ZipEntry entry = ((ZipEntry) entries.nextElement());
String entryName = entry.getName();
if (entryName.contains("../")) {
Log.e("ZipUtils", "it's dangerous!");//防止被利用漏洞惡意修改文件
return files;
}
if (!unzipChildFile(destDir, files, zip, entry)) return files;
}
} else {
while (entries.hasMoreElements()) {
ZipEntry entry = ((ZipEntry) entries.nextElement());
String entryName = entry.getName();
if (entryName.contains("../")) {
Log.e("ZipUtils", "it's dangerous!");
return files;
}
if (entryName.contains(keyword)) {
if (!unzipChildFile(destDir, files, zip, entry)) return files;
}
}
}
} finally {
zip.close();
}
return files;
}
private static boolean unzipChildFile(final File destDir,final List<File> files,final ZipFile zip,final ZipEntry entry)
throws IOException {
File file = new File(destDir, entry.getName());
files.add(file);
if (entry.isDirectory()) {
return createOrExistsDir(file);//創建文件夾
} else {
if (!createOrExistsFile(file)) return false;
InputStream in = null;
OutputStream out = null;
try {
in = new BufferedInputStream(zip.getInputStream(entry));
out = new BufferedOutputStream(new FileOutputStream(file));
byte buffer[] = new byte[BUFFER_LEN];
int len;
while ((len = in.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
} finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
}
return true;
}
備註:代碼實例來自開源框架AndroidUtilCode,https://github.com/Blankj/AndroidUtilCode 開源了各種開發過程中的常用工具,五星推薦。