Hatena::Groupnodejs

Node.jsで遊ぶよ

2010-10-14

Gzip

17:01

Node.js の標準ライブラリはかなり下層の API に近くて、http.client とかは Gzip の展開すらしない。レスポンスが全部終わる前のバイトを取れるんだから当然か。

node-httpclient を使うとそこらへんも面倒見てくれるみたいだけど、そのためには node-compress という別のライブラリコンパイルしないといけない。

じゃあ使ってみましょってことで、node-compress は npm には無いみたいなので、git clone してきて make && sudo make install でインストールした。

まず圧縮から。これは node-compress の README に載ってるのをちょっと弄っただけ。

var compress=require("./compress");
function showBytes(byteString) {
  return Array.prototype.map.call(byteString, function(b) {return b.charCodeAt(0);}).join(' ')
}

// Create gzip stream
var gzip=new compress.Gzip;
gzip.init();

// Pump data to be compressed
var gzdata1 = gzip.deflate("あいうえお", "utf-8"); 
console.log(showBytes(gzdata1));
// => 31 139 8 0 0 0 0 0 0 3

var gzdata2 = gzip.deflate("かきくけこ", "utf-8"); 
console.log(showBytes(gzdata2));
// => (出力なし)

var gzdata3 = gzip.end();
console.log(showBytes(gzdata3));
// => 5 193 129 9 0 32 8 0 193 217 63 68 162 16 137 70 252 69 188 147 37 33 41 91 142 92 41 105 121 242 7 169 233 190 47 30 0 0 0

// Normally stream this out as its generated, but just print here
var gzdata = gzdata1+gzdata2+gzdata3;
console.log(showBytes(gzdata));
// => 31 139 8 0 0 0 0 0 0 3 5 193 129 9 0 32 8 0 193 217 63 68 162 16 137 70 252 69 188 147 37 33 41 91 142 92 41 105 121 242 7 169 233 190 47 30 0 0 0

まあこんな感じ。

展開のほうは node-compress のテストには複数回に分けてやる方法が書いてあるが、これは binary では使えても utf-8 では無理っぽいので、一回で全部やる必要があるらしい。

var gunzip=new compress.Gunzip;
gunzip.init();
console.log(gunzip.inflate(gzdata, 'utf-8'));
// => あいうえおかきくけこ
gunzip.end();

なんでこんなインターフェイスにしたんだろう…普通に圧縮展開だけでいいのに。

あと、Node.js の組み込みオブジェクトである Buffer を扱えるようになるともっと便利になるんだけど、書かれたのが今年の1月だからしょうがないか。(Buffer は確か4月から)


Buffer

17:01

Node.js でサポートされてるエンコーディングutf-8, ascii, binary のどれか。あと Buffer というオブジェクトがある。

それぞれの意味は

> a = 'あいうえお'
'あいうえお'
> b = new Buffer(Buffer.byteLength(a))
<Buffer 02 00 00 00 00 00 00 00 02 00 00 00 00 00 00>
> b.write(a, 'utf-8')
15
> b.toString('utf-8')
'あいうえお'
> b.toString('ascii')
'あいうえお'
> b.toString('binary')
'あいうえお'
> b.toString('utf-8').length
5
> b.toString('ascii').length
5
> b.toString('binary').length
15
> 

こんな感じ。new Buffer(Buffer.byteLength(a)) がポイント。

上だけだと asciiutf-8 の違いがよくわからないな。僕もよくわかってない。