Android zip文件壓縮與解壓

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壓縮一共分爲三步:

  1. 獲取相應的ZipOutputStream;
  2. 判斷是否是文件夾

​ (1)是:遞歸;

​ (2)否:根據文件路徑、文件名等獲取相應的ZipEntry,然後將該文件寫入ZipOutputStream;

  1. 關閉相應的輸出流;

    /**
     * 壓縮文件
     * @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 開源了各種開發過程中的常用工具,五星推薦。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章