JavaでDeflateしてBase64したやつをRubyでBase64してInflateできるか確認
ちょいと多めのテキストデータをサーバに送るとき、帯域を抑えたいからDeflateしてBase64して送ろう!と思ったが、バグとか基準にしているRFCが違うとかそういうのでサーバサイドであるRubyと相互変換できなかったらヤだなぁと思って試してみた。
deflate and base64encode
String original = "リア充爆発しろ!!!!" ; byte[] dataByte = original.getBytes(); System.out.println("original size:" + dataByte.length); Deflater def = new Deflater(); def.setLevel(Deflater.BEST_COMPRESSION); def.setInput(dataByte); def.finish(); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(dataByte.length); byte[]buf = new byte[1024]; while(!def.finished()) { int compByte = def.deflate(buf); byteArrayOutputStream.write(buf, 0, compByte); } byteArrayOutputStream.close(); byte[] compData = byteArrayOutputStream.toByteArray(); String encoded = Base64.encodeToString(compData, Base64.DEFAULT); System.out.println("deflated size:" + compData.length); System.out.println("base64encoded size:" + encoded.length()); System.out.println("base64:" + encoded);
original size:33 deflated size:35 base64:eNp73LzqcdOip62tzzvans/c9bhx+uOm3vd7GuEIAIHtFtM= base64encoded size:49
今回は元の文字列が短いので逆にデータ量は多くなった。
1.9.3-p0 :001 > require 'zlib' => true 1.9.3-p0 :002 > require 'base64' => true 1.9.3-p0 :003 > decoded = Base64.decode64("eNp73LzqcdOip62tzzvans/c9bhx+uOm3vd7GuEIAIHtFtM=") => "x\xDA{\xDC\xBC\xEAq\xD3\xA2\xA7\xAD\xAD\xCF;\xDA\x9E\xCF\xDC\xF5\xB8q\xFA\xE3\xA6\xDE\xF7{\x1A\xE1\b\x00\x81\xED\x16\xD3" 1.9.3-p0 :004 > Zlib::Inflate.inflate(decoded).force_encoding("UTF-8") => "リア充爆発しろ!!!!"
戻った。
ちなみに元データを100回繰り返すと圧縮効果は相当でる。
int count = 100; StringBuilder stringBuilder = new StringBuilder(); for(int i = count; i -->0;) { stringBuilder.append("リア充爆発しろ!!!!"); } String original = stringBuilder.toString();
original size:3300 deflated size:64 base64:eNp73LzqcdOip62tzzvans/c9bhx+uOm3vd7GuHo8aiCUQWjCkYVjCoYVTCqYFTBqIJRBaMKRhUM base64encoded size:90 HQUAavnqgQ==
ただ同じ文字列が単調に出現するからそうとう圧縮されたけど、普通はここまで圧縮しないと思う。
っていうか、なんでJavaのDeflateあんなに手順がいるの!