記一次字符串壓縮操作

記一次字符串壓縮操作

項目中遇到一個場景:需要將一批數據發送到APP端,且實際應用場景中,對數據的長度有一定的限制,於是就需要用到字符串壓縮。
APP端使用Java,後端使用Golang,使用gzip壓縮,同時涉及到了base64編碼,中文和西歐字符集轉碼。

過程描述

  1. 後端:

    1. 字符集轉換 參考自:一個複雜的中文編碼問題
    2. 壓縮字符串
    3. 使用base64編碼爲可見字符
    4. 網絡傳輸
  2. APP端

    1. 接收網絡響應
    2. base64解碼,得到一個字節數組(壓縮的)
    3. gzip讀取壓縮的字節流,解壓縮
    4. 轉碼爲中文

示例代碼

所有示例代碼可以在這裏找到

  1. server端
func compress(s string) string {
    //使用GBK字符集encode
    gbk, err := simplifiedchinese.GBK.NewEncoder().Bytes([]byte(s))
    if err != nil {
        logrus.Error(err)
        return ""
    }

    //轉爲ISO8859_1,也就是latin1字符集
    latin1, err := charmap.ISO8859_1.NewDecoder().Bytes(gbk)
    if err != nil {
        return ""
    }

    //使用gzip壓縮
    var buf bytes.Buffer
    zw := gzip.NewWriter(&buf)

    _, err = zw.Write(latin1)
    if err != nil {
        logrus.Fatal(err)
    }

    if err := zw.Close(); err != nil {
        logrus.Fatal(err)
    }

    //使用base64編碼
    encoded := base64.StdEncoding.EncodeToString(buf.Bytes())
    fmt.Println(encoded)
    return encoded
}
  1. APP端
private static String uncompress(String s) throws IOException {

        //base64 decode
        byte[] byteArray = Base64.getDecoder().decode(s);
        ByteArrayInputStream bis = new ByteArrayInputStream(byteArray);
        
        //gzip解壓
        GZIPInputStream gis = new GZIPInputStream(bis);
        BufferedReader br = new BufferedReader(new InputStreamReader(gis, "UTF-8"));
        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = br.readLine()) != null) {
            sb.append(line);
        }
        br.close();
        gis.close();
        bis.close();

        //使用latin1字符集獲得bytes
        byte[] latin1 = sb.toString().getBytes("ISO_8859_1");
        //轉換回GBK
        return new String(latin1, "GBK");
    }

使用base64編碼,主要是因爲經過gzip壓縮後數據,直接轉成字符串的話,會有很多不可見字符,這樣在傳輸過程中,通常會被服務端框架轉義,從而失真。
代碼僅作爲示例使用,實際業務編碼請注意檢查錯誤和異常等。

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