在實際的應用場景中,特別是對外傳輸數據時,將原始數據壓縮以後丟出去,能夠說是很是常見的一個case了,日常卻是沒有直接使用JDK原生的壓縮工具類,使用Protosutff和Kryo的機會較多,正好在實際的工做場景中遇到了,如今簡單的看下使用姿式html
主要藉助的就是Deflater, Inflater兩個工具類,其使用姿式以下java
public static String uncompress(byte[] input) throws IOException { Inflater inflater = new Inflater(); inflater.setInput(input); ByteArrayOutputStream baos = new ByteArrayOutputStream(input.length); try { byte[] buff = new byte[1024]; while (!inflater.finished()) { int count = inflater.inflate(buff); baos.write(buff, 0, count); } } catch (Exception e) { e.printStackTrace(); } finally { baos.close(); } inflater.end(); byte[] output = baos.toByteArray(); return new String(output, "UTF-8"); } public static byte[] compress(byte[] data) throws IOException { byte[] output; Deflater compress = new Deflater(); compress.reset(); compress.setInput(data); compress.finish(); ByteArrayOutputStream bos = new ByteArrayOutputStream(data.length); try { byte[] buf = new byte[1024]; while (!compress.finished()) { int i = compress.deflate(buf); bos.write(buf, 0, i); } output = bos.toByteArray(); } catch (Exception e) { output = data; e.printStackTrace(); } finally { bos.close(); } compress.end(); return output; }
一個簡單的測試git
public static void main(String[] args) throws IOException { StringBuilder builder = new StringBuilder(); for (int i = 0; i < 200; i++) { builder.append('a' + (new Random().nextInt() * 26)); } String text = builder.toString(); byte[] compres = compress(text.getBytes()); System.out.println(compres.length + " : " + text.getBytes().length); String res = uncompress(compres); System.out.println("uncompress! \n" + text + "\n" + res); }
輸出結果github
1011 : 1974 uncompress! 1159641073884270587-148914555-876348695-140903655914152858511750740619-504526839109631208315104321891746743931-228808979-1303586499-19431155411964999751-1784318475-954798177-1812907183-831342707-3149322476028964551802022597-269963287-6384200011467670385844411707877038035412670417-1119826115558346219-959513147646693111435818855-32626587-18184494797054550038966016212145089137523302939171183465807867207-5294746515903446057333959811216956465-11772186456902770294071039871896527261-126190055310658640239029635411410052621945318513-1099749933-2044334159884087065-1705740759-1313321287-1408007761-12659778231544522691472523171153203782987609706919936632357801287155512488271333115291-1121944135941979389-179880545175884207196204559-2097788799145839653133892163716038492252042396151523357607329397509-2453452914618397691174247129-542507633-1893723573237001573-84175562119492726191070559557-875056377-1763237523-662399435-170798495-12405874171550890051-1938474621-701626601-1246867757-1138873077164155271023310391435811251050668025181338411-7641844471088518205-1570482881-1690731767-954924683-213656821149494003-544272515-9322840891981997411254437701-183054198720365002211448655569-54030518916444117051191350451-900732825-2072105047160877226512403288354302424851213478975-57604286986096457192173124564975571096304687-213425653510984804314132356831371957625714091709-327695077-182546427-372769058150182636433743131293942149315625331-1010625457741185365-81246881-565236593-1937214707-2090999425-1673181289-1110250756450022071917863643-127217577910228760391902441297-31318475-535669437-1151216791170962161121375401911260706331-1873591233-495048743-8876731551362670289-686442615-6752584831233249861-3467630691547253127-345092207-908370541-1788351797644350365-67770933-4703179231930520693138257968522450375-1171662023-5791753311816936409-1745781765-922801857281665531707439257928142703-367587763829971705455779401438501763-1398546079-606883161-924403277-1617582925-2005411841279115903 1159641073884270587-148914555-876348695-140903655914152858511750740619-504526839109631208315104321891746743931-228808979-1303586499-19431155411964999751-1784318475-954798177-1812907183-831342707-3149322476028964551802022597-269963287-6384200011467670385844411707877038035412670417-1119826115558346219-959513147646693111435818855-32626587-18184494797054550038966016212145089137523302939171183465807867207-5294746515903446057333959811216956465-11772186456902770294071039871896527261-126190055310658640239029635411410052621945318513-1099749933-2044334159884087065-1705740759-1313321287-1408007761-12659778231544522691472523171153203782987609706919936632357801287155512488271333115291-1121944135941979389-179880545175884207196204559-2097788799145839653133892163716038492252042396151523357607329397509-2453452914618397691174247129-542507633-1893723573237001573-84175562119492726191070559557-875056377-1763237523-662399435-170798495-12405874171550890051-1938474621-701626601-1246867757-1138873077164155271023310391435811251050668025181338411-7641844471088518205-1570482881-1690731767-954924683-213656821149494003-544272515-9322840891981997411254437701-183054198720365002211448655569-54030518916444117051191350451-900732825-2072105047160877226512403288354302424851213478975-57604286986096457192173124564975571096304687-213425653510984804314132356831371957625714091709-327695077-182546427-372769058150182636433743131293942149315625331-1010625457741185365-81246881-565236593-1937214707-2090999425-1673181289-1110250756450022071917863643-127217577910228760391902441297-31318475-535669437-1151216791170962161121375401911260706331-1873591233-495048743-8876731551362670289-686442615-6752584831233249861-3467630691547253127-345092207-908370541-1788351797644350365-67770933-4703179231930520693138257968522450375-1171662023-5791753311816936409-1745781765-922801857281665531707439257928142703-367587763829971705455779401438501763-1398546079-606883161-924403277-1617582925-2005411841279115903
上面這個運做的還挺好,但在接入使用時,老是提示java.util.zip.DataFormatException: incorrect header check
, 由於接受的是第三方傳遞過來的壓縮數據,比較坑爹的是對方就寫了個Deflater壓縮,而後什麼都沒有了,那麼這個是啥緣由呢?app
其實看下Deflater的構造方法,發現還能夠傳一個boolean值(nowrap), 官方說明是框架
/** * Creates a new compressor using the specified compression level. * If 'nowrap' is true then the ZLIB header and checksum fields will * not be used in order to support the compression format used in * both GZIP and PKZIP. * @param level the compression level (0-9) * @param nowrap if true then use GZIP compatible compression */ public Deflater(int level, boolean nowrap) { this.level = level; this.strategy = DEFAULT_STRATEGY; this.zsRef = new ZStreamRef(init(level, DEFAULT_STRATEGY, nowrap)); }
簡單來講,就是壓縮時,若是nowrap爲true,那麼解壓時也要爲true;不然對不上時,就會拋異常dom
接下來簡單對比下兩種不一樣傳參的狀況,首先更新下工具類函數
public static String uncompress(byte[] input, boolean nowrap) throws IOException { Inflater inflater = new Inflater(nowrap); inflater.setInput(input); ByteArrayOutputStream baos = new ByteArrayOutputStream(input.length); try { byte[] buff = new byte[1024]; while (!inflater.finished()) { int count = inflater.inflate(buff); baos.write(buff, 0, count); } } catch (Exception e) { e.printStackTrace(); } finally { baos.close(); } inflater.end(); byte[] output = baos.toByteArray(); return new String(output); } public static byte[] compress(byte[] data, boolean nowrap) throws IOException { byte[] output; Deflater compress = new Deflater(Deflater.DEFAULT_COMPRESSION, nowrap); compress.reset(); compress.setInput(data); compress.finish(); ByteArrayOutputStream bos = new ByteArrayOutputStream(data.length); try { byte[] buf = new byte[1024]; while (!compress.finished()) { int i = compress.deflate(buf); bos.write(buf, 0, i); } output = bos.toByteArray(); } catch (Exception e) { output = data; e.printStackTrace(); } finally { bos.close(); } compress.end(); return output; }
測試以下工具
public static void main(String[] args) throws IOException { StringBuilder builder = new StringBuilder(); for (int i = 0; i < 1000; i++) { builder.append('a' + (new Random().nextInt() * 26)); } String text = builder.toString(); byte[] compres = compress(text.getBytes(), true); System.out.println(compres.length + " : " + text.getBytes().length); String res = uncompress(compres, true); System.out.println(res.equals(text)); byte[] compres2 = compress(text.getBytes(), false); System.out.println(compres2.length + " : " + text.getBytes().length); String res2 = uncompress(compres2, false); System.out.println(res2.equals(text)); }
輸出結果以下,從大小來看,前者小那麼一點點性能
5086 : 9985 true 5092 : 9985 true
通常來講,jdk自帶的壓縮與解壓,除了方便以外,可能優點並非那麼的大,這裏盜一張網上的對比表格
如下來自: [java]序列化框架性能對比(kryo、hessian、java、protostuff)
優勢 | 缺點 | |
---|---|---|
kryo | 速度快,序列化後體積小 | 跨語言支持較複雜 |
hessian | 默認支持跨語言 | 較慢 |
protostuff | 速度快,基於protobuf | 需靜態編譯 |
Protostuff-Runtime | 無需靜態編譯,但序列化前需預先傳入schema | 不支持無默認構造函數的類,反序列化時需用戶本身初始化序列化後的對象,其只負責將該對象進行賦值 |
jdk | 使用方便,可序列化全部類 | 速度慢,佔空間 |
其次,在使用java的壓縮與解壓時,須要注意下,nowrap這個參數,須要保持一致,不然會報錯
一灰灰的我的博客,記錄全部學習和工做中的博文,歡迎你們前去逛逛
盡信書則不如,已上內容,純屬一家之言,因我的能力有限,不免有疏漏和錯誤之處,如發現bug或者有更好的建議,歡迎批評指正,不吝感激
一灰灰blog
知識星球