LoginSignup
0
0

JavaScript: CompressionStreamを記る!

Last updated at Posted at 2024-01-28

またつまらぬものを記ってしまったかどうかは定かではないかもしれませんが、browserで組み込み圧縮伸長関数が実装されているので紹介します。その実態はdeflateとその包括形式であるgzipとなります。非常に高速ですが地味に使いにくく、圧縮加減も指定できないという、とても素晴らしい仕様となっております。
まずどう不便かと言うとObjectを複数作る必要がある点と、Promiseを経由する必要がある点です。面倒臭い仕様と言わざるを得ません。単純に書くと以下のようになります。

(async()=>{
	var c=new CompressionStream("gzip"),//"deflate", "deflate-raw"も可
	w=c.writable.getWriter();
	//圧縮したいArrayBufferを渡す
	w.write(new Uint8Array([84,104,97,116,32,116,104,97,116,32]));
	//追加も可
	w.write(new Uint8Array([105,115,32,105,115,32,116,104,97,116,32,116,104,97,116]));
	//終了. 以後追記不可
	w.close();
	//圧縮後のArrayBuffer取得
	c=await new Response(c.readable).arrayBuffer();

	//伸長処理
	var d=new DecompressionStream("gzip");
	w=d.writable.getWriter();
	w.write(c);
	w.close();
	d=await new Response(d.readable).arrayBuffer()
})()

それではこの組み込み関数様を使ってbrowser式file圧縮伸長programを書いてみましょう。

<input id=g type=checkbox>gzip
<input id=d type=checkbox>inflate
<input id=f type=file><script>
f.onchange=a=>{
	with(new FileReader)
		readAsArrayBuffer(f.files[0]),
		onload=async(a,b,c)=>{
			b=new(d.checked?DecompressionStream:CompressionStream)(g.checked?"gzip":"deflate"),
			c=b.writable.getWriter(a=new Uint8Array(result)),c.close(c.write(a)),
			e.href=URL.createObjectURL(new Blob([new Uint8Array(await new Response(b.readable).arrayBuffer())]))
		}
}
</script><a id=e download>DL

実はもっと単純に書けます

(async()=>{
	//圧縮させるArrayBuffer
	var c=new Uint8Array([84,104,97,116,32,116,104,97,116,32]);
	//圧縮
	c=await new Response(new Blob([c]).stream().pipeThrough(new CompressionStream("gzip"))).arrayBuffer();
	//伸長
	c=await new Response(new Blob([c]).stream().pipeThrough(new DecompressionStream("gzip"))).arrayBuffer();
})()
<select id=s>
	<option>deflate-raw<option>deflate<option>gzip
</select>
<input id=d type=checkbox>decode
<input id=f type=file>
<script>
f.onchange=a=>{
	with(new FileReader)
		readAsArrayBuffer(f.files[0]),
		onload=async a=>e.href=URL.createObjectURL(new Blob([await new Response(new Blob([result]).stream().pipeThrough(new(d.checked?DecompressionStream:CompressionStream)(s.options[s.selectedIndex].text))).arrayBuffer()]))
}
</script><a id=e download>DL

動作検証

See the Pen deflate/gzip/inflate test by xezz (@xezz) on CodePen.

更に短縮

制御文字が山盛りなのでbase64形式です。元は367 bytes。復号してhtmlとして扱います

PHN2ZyBvbmxvYWQ9J2ZvcihhPWByZRJvbhFmaWxlEGVjD2NoD2sOdBJhbQxpbnB1dAsgaWQ9CW5ldyAIb3B0aREHPAc+ZGVmbGF0ZQZzZWwPdAU8CyB0eXBlPQQoCEJsb2IoW2FdKQNvbXASc3NpEVMMAi5hcnJheUJ1ZmZlcigpLnRoZW4oYT0+ATwFCXM+Bi1yYXcGPAc+Z3ppcDwvBT4EDmJveAlkPmQPb2RlBBAgEQs9IhBzWzBdAQhSZXNwEXNlAy5zDCgpLnBpcGVUaHJvdWdoKAgoZC4OZWQ/RA8COkMCKShzLgdzW3MuBWVkSW5kZXhdLnRleHQpKSkBZS5oEmY9c2VsZi5VUkwuYxJhdGVPYmoPdFVSTAMpKSkiPjxhCWUgZG93bmxvYWQ+CGA7dD0vWwEtEl0vLmV4ZWMoYSk7KXdpdGgoYS5zcGxpdCh0KSlhPWpvaW4oc2hpZnQoKSk7d3JpdGUoYSknPg
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0