1.引言
最近在做項目中,平臺提供一個http服務給其他系統調用,然後我接收到其他系統的json格式的報文後去解析,然後用拿到的數據去調用corba服務,我再把corba的返回值封裝完成json字符串返回給外部系統。遇到一個接口去調用corba服務,然後corba返回的數據經過封裝後字符串的長度達到7M左右,導致http客戶端無法正常的接收完所有的數據。你可能會說這個接口設計的不合理,爲什麼不增加查詢條件把查詢條件範圍縮小一點?但是,這個不是本節要討論的內容,主要是因爲corba服務已經發布用了很久且不在此次項目改造範圍之內,再者這個corba服務已經上線用了N久,輕易的改變可能會導致未知的錯誤。籤於此,我想到可以把json格式的字符串給壓縮,然後客戶端再解壓。(一是字符串的壓縮比例比較的高,二是字符串的壓縮和解壓實現起來也比較簡單)。雖然,最後沒有用到字符串的壓縮和解壓的方式,而是修改客戶端(1.http客戶端進一步精確查詢條件 2.讀取返回數據流採用循環讀取的方式)來解決此問題,我還是把字符串的壓縮和解壓做一下簡單的記錄。
2.關於壓縮與解壓
壓縮算法有多種,我說知道和接觸有java I/O自帶的zip和gzip兩種方式。
本節主要來簡單介紹一下在系統交互之間遇到大容量的字符串數據交互時,採用一端壓縮,另一端再解壓的方式來發送和接收數據。
關於此次的壓縮和解壓用到的主要就是GZIPOutputStream和GZIPInputStream類,此類的相關介紹在JDK中有詳細的介紹,這裏就不再累述了。
3.代碼如下:
- ZipStrUtil.java
- package gzip;
- import java.io.ByteArrayInputStream;
- import java.io.ByteArrayOutputStream;
- import java.io.IOException;
- import java.util.zip.GZIPInputStream;
- import java.util.zip.GZIPOutputStream;
- /**
- *
- *Module: ZipUtil.java
- *Description: 對字符串的壓縮及解壓
- *Company:
- *Author: pantp
- *Date: May 6, 2012
- */
- public class ZipStrUtil {
- public static void main(String[] args) throws IOException {
- // 字符串超過一定的長度
- String str = "ABCdef123中文~!@#$%^&*()_+{};/1111111111111111111111111AAAAAAAAAAAJDLFJDLFJDLFJLDFFFFJEIIIIIIIIIIFJJJJJJJJJJJJALLLLLLLLLLLLLLLLLLLLLL" +
- "LLppppppppppppppppppppppppppppppppppppppppp===========================------------------------------iiiiiiiiiiiiiiiiiiiiiii";
- System.out.println("\n原始的字符串爲------->" + str);
- float len0=str.length();
- System.out.println("原始的字符串長度爲------->"+len0);
- String ys = compress(str);
- System.out.println("\n壓縮後的字符串爲----->" + ys);
- float len1=ys.length();
- System.out.println("壓縮後的字符串長度爲----->" + len1);
- String jy = unCompress(ys);
- System.out.println("\n解壓縮後的字符串爲--->" + jy);
- System.out.println("解壓縮後的字符串長度爲--->"+jy.length());
- System.out.println("\n壓縮比例爲"+len1/len0);
- //判斷
- if(str.equals(jy)){
- System.out.println("先壓縮再解壓以後字符串和原來的是一模一樣的");
- }
- }
- /**
- * 字符串的壓縮
- *
- * @param str
- * 待壓縮的字符串
- * @return 返回壓縮後的字符串
- * @throws IOException
- */
- public static String compress(String str) throws IOException {
- if (null == str || str.length() <= 0) {
- return str;
- }
- // 創建一個新的 byte 數組輸出流
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- // 使用默認緩衝區大小創建新的輸出流
- GZIPOutputStream gzip = new GZIPOutputStream(out);
- // 將 b.length 個字節寫入此輸出流
- gzip.write(str.getBytes());
- gzip.close();
- // 使用指定的 charsetName,通過解碼字節將緩衝區內容轉換爲字符串
- return out.toString("ISO-8859-1");
- }
- /**
- * 字符串的解壓
- *
- * @param str
- * 對字符串解壓
- * @return 返回解壓縮後的字符串
- * @throws IOException
- */
- public static String unCompress(String str) throws IOException {
- if (null == str || str.length() <= 0) {
- return str;
- }
- // 創建一個新的 byte 數組輸出流
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- // 創建一個 ByteArrayInputStream,使用 buf 作爲其緩衝區數組
- ByteArrayInputStream in = new ByteArrayInputStream(str
- .getBytes("ISO-8859-1"));
- // 使用默認緩衝區大小創建新的輸入流
- GZIPInputStream gzip = new GZIPInputStream(in);
- byte[] buffer = new byte[256];
- int n = 0;
- while ((n = gzip.read(buffer)) >= 0) {// 將未壓縮數據讀入字節數組
- // 將指定 byte 數組中從偏移量 off 開始的 len 個字節寫入此 byte數組輸出流
- out.write(buffer, 0, n);
- }
- // 使用指定的 charsetName,通過解碼字節將緩衝區內容轉換爲字符串
- return out.toString("GBK");
- }
- }
說明:
字符串長度很小的時候,測試時你會發現壓縮後的長度竟然變長了,字符串必須達到一定長度,壓縮比例就可以明顯看到很大。