BinaryWriterで文字列を記録すると?

| トラックバック(0)

Streamにバイナリを記録するには、BinaryWriterを使うと便利。BinaryWriterで書いた順番にBinaryReaderで読み込めば、異なるデータ型が連続する構造体などを簡単にバイト配列化することができる。

数値型の固定長サイズの変数はバイトサイズ分のデータが生成され、可変長文字列はバイトサイズが可変なので文字列のバイト長が文字列バイトの前に記録される。

ここまでは理解していたが、文字列のバイト数はどのように記録されるのか。2バイトなのか、4バイトなのか?

MSDNの説明ではよくわからないので、試してみた。

まず、"abcde"の5文字だけを記録してバイナリのダンプを見てみると・・・

05 61 62 63 64 65

このようになった。先頭の 05 が文字列のバイト配列を示すプレフィックスである。当然、このままでは255バイトまでしか記録できない。そこで、255文字を記録してダンプを見てみた。

ff 01 61 62 63 64 65 61 62 63 64 65 61 62 63 64
65 61 62 63 64 65 61 62 63 64 65 61 62 63 64 65 ...

このようにプレフィックスは「ff 01」。さきほど1バイトだったものが2バイトになっている。2進数になおすと

1111 1111  0000 0001

これを見る限り、プレフィックスは最上位ビットをフラグとして使用している模様。プレフィックスバイトの最上位ビットが 1 の場合は、次のバイトもプレフィックスである、というフラグではないだろうか。そのようにすれば、文字列長にあわせてプレフィックス長が変化するので、データに無駄がない。これは、MIDIデータのタイムラインを記録するときにも使われる簡易圧縮テクニックのひとつ。

 

では本当にそのような仕組みになっているのか検証。

 

まず、文字列バイト数を表すビットだけ抜き出すと・・・。

_111 1111 _000 0001

となる。これをリトルエンディアンで隙間を埋めると

xx00 0000 1111 1111 = 255

という数値が導かれる。

次に、50万文字で試してみると、プレフィックス部分は

a0 c2 1e

となった。2進数になおすと

1010 0000  1100 0010  0001 1110

ここから最上位ビットをはずして、

_010 0000  _100 0010  _001 1110

リトルエンディアンで並び替える。

___0 0111  1010  0001  0010 0000 = 500,000

 

おおお!

結構あてずっぽに試してみたのだけど、あっていたらしい♪

トラックバック(0)

トラックバックURL: http://wiz.came.ac/mt/mt-tb.cgi/21