Android總結之Gzip/Zip壓縮

總李寫程式碼發表於2016-08-20

前言:

     做過Android網路開發的都知道,在網路傳輸中我們一般都會開啟GZIP壓縮,但是出於刨根問底的天性僅僅知道如何開啟就不能滿足俺的好奇心的,所以想著寫個demo測試一下比較常用的兩個資料壓縮方式,GZIP/ZIP壓縮。

首先認識一下GZIP壓縮

GZIP是網站壓縮加速的一種技術,對於開啟後可以加快我們網站的開啟速度,原理是經過伺服器壓縮,客戶端瀏覽器快速解壓的原理,可以大大減少了網站的流量。GZIP最早由Jean-loup Gailly和Mark Adler建立,用於UNIX系統的檔案壓縮。我們在Linux中經常會用到字尾為.gz的檔案,它們就是GZIP格式的。現今已經成為Internet 上使用非常普遍的一種資料壓縮格式,或者說一種檔案格式。HTTP協議上的GZIP編碼是一種用來改進WEB應用程式效能的技術。大流量的WEB站點常常使用GZIP壓縮技術來讓使用者感受更快的速度。這一般是指WWW伺服器中安裝的一個功能,當有人來訪問這個伺服器中的網站時,伺服器中的這個功能就將網頁內容壓縮後傳輸到來訪的電腦瀏覽器中顯示出來.一般對純文字內容可壓縮到原大小的40%.這樣傳輸就快了,效果就是你點選網址後會很快的顯示出來.當然這也會增加伺服器的負載. 一般伺服器中都安裝有這個功能模組的

開GZIP有什麼好處?Gzip開啟以後會將輸出到使用者瀏覽器的資料進行壓縮的處理,這樣就會減小通過網路傳輸的資料量,提高瀏覽的速度。

那麼在Android上怎麼實現壓縮的呢?相關壓縮api詳見http://www.apihome.cn/api/android/java.util.zip

   /**
     * Gzip 壓縮資料
     *
     * @param unGzipStr
     * @return
     */
    public static String compressForGzip(String unGzipStr) {

        if (TextUtils.isEmpty(unGzipStr)) {
            return null;
        }
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            GZIPOutputStream gzip = new GZIPOutputStream(baos);
            gzip.write(unGzipStr.getBytes());
            gzip.close();
            byte[] encode = baos.toByteArray();
            baos.flush();
            baos.close();
            return Base64Encoder.encode(encode);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * Gzip解壓資料
     *
     * @param gzipStr
     * @return
     */
    public static String decompressForGzip(String gzipStr) {
        if (TextUtils.isEmpty(gzipStr)) {
            return null;
        }
        byte[] t = Base64Decoder.decodeToBytes(gzipStr);
        try {
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            ByteArrayInputStream in = new ByteArrayInputStream(t);
            GZIPInputStream gzip = new GZIPInputStream(in);
            byte[] buffer = new byte[BUFFERSIZE];
            int n = 0;
            while ((n = gzip.read(buffer, 0, buffer.length)) > 0) {
                out.write(buffer, 0, n);
            }
            gzip.close();
            in.close();
            out.close();
            return out.toString();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

 

然後我們再來認識一下ZIP壓縮

ZIP,是一個計算機檔案的壓縮的演算法,原名Deflate(真空),發明者為菲爾·卡茨(Phil Katz)),他於1989年1月公佈了該格式的資料。ZIP通常使用字尾名“.zip”,它的MIME格式為 application/zip 。目前,ZIP格式屬於幾種主流的壓縮格式之一,其競爭者包括RAR格式以及開放原始碼的7-Zip格式。從效能上比較,RAR格式較ZIP格式壓縮率較高,而7-Zip由於提供了免費的壓縮工具而逐漸在更多的領域得到應用。

 

看看具體實現:

 /**
     * Zip 壓縮資料
     *
     * @param unZipStr
     * @return
     */
    public static String compressForZip(String unZipStr) {

        if (TextUtils.isEmpty(unZipStr)) {
            return null;
        }
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ZipOutputStream zip = new ZipOutputStream(baos);
            zip.putNextEntry(new ZipEntry("0"));
            zip.write(unZipStr.getBytes());
            zip.closeEntry();
            zip.close();
            byte[] encode = baos.toByteArray();
            baos.flush();
            baos.close();
            return Base64Encoder.encode(encode);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * Zip解壓資料
     *
     * @param zipStr
     * @return
     */
    public static String decompressForZip(String zipStr) {

        if (TextUtils.isEmpty(zipStr)) {
            return null;
        }
        byte[] t = Base64Decoder.decodeToBytes(zipStr);
        try {
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            ByteArrayInputStream in = new ByteArrayInputStream(t);
            ZipInputStream zip = new ZipInputStream(in);
            zip.getNextEntry();
            byte[] buffer = new byte[BUFFERSIZE];
            int n = 0;
            while ((n = zip.read(buffer, 0, buffer.length)) > 0) {
                out.write(buffer, 0, n);
            }
            zip.close();
            in.close();
            out.close();
            return out.toString("UTF-8");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

 

寫個例子測試一下效果:

        List<Person> personList = new ArrayList<>();
        int testMaxCount = 500;//測試的最大資料條數
        //新增測試資料
        for (int i = 0; i < testMaxCount; i++) {
            Person person = new Person();
            person.setAge(i);
            person.setName(String.valueOf(i));
            personList.add(person);
        }
        //FastJson生成json資料
        String jsonData = JsonUtils.objectToJsonForFastJson(personList);
        Log.e("MainActivity", "壓縮前json資料 ---->" + jsonData);
        Log.e("MainActivity", "壓縮前json資料長度 ---->" + jsonData.length());

        //Gzip壓縮
        long start = System.currentTimeMillis();
        String gzipStr = ZipUtils.compressForGzip(jsonData);
        long end = System.currentTimeMillis();
        Log.e("MainActivity", "Gzip壓縮耗時 cost time---->" + (end - start));
        Log.e("MainActivity", "Gzip壓縮後json資料 ---->" + gzipStr);
        Log.e("MainActivity", "Gzip壓縮後json資料長度 ---->" + gzipStr.length());

        //Gzip解壓
        start = System.currentTimeMillis();
        String unGzipStr = ZipUtils.decompressForGzip(gzipStr);
        end = System.currentTimeMillis();
        Log.e("MainActivity", "Gzip解壓耗時 cost time---->" + (end - start));
        Log.e("MainActivity", "Gzip解壓後json資料 ---->" + unGzipStr);
        Log.e("MainActivity", "Gzip解壓後json資料長度 ---->" + unGzipStr.length());

        //Zip壓縮
        start = System.currentTimeMillis();
        String zipStr = ZipUtils.compressForZip(jsonData);
        end = System.currentTimeMillis();
        Log.e("MainActivity", "Zip壓縮耗時 cost time---->" + (end - start));
        Log.e("MainActivity", "Zip壓縮後json資料 ---->" + zipStr);
        Log.e("MainActivity", "Zip壓縮後json資料長度 ---->" + zipStr.length());

執行耗時對比:

資料壓縮比對比:

從上面可以看出兩者壓縮效率和壓縮比相差無幾。可能我測試的資料比較小

接下來看下如何開啟網路GZIP壓縮

在android 客戶端 request 頭中加入 "Accept-Encoding", "gzip" ,來讓伺服器傳送gzip 資料。

具體實現這這裡不再做具體介紹分享一個連結:http://blog.csdn.net/kepoon/article/details/7482096

 

相關文章