Tcl – バイナリデータの操作(2) -binary format-

binaryコマンドの日本語の扱いについて

文字コードの話をすると、1冊本が出来るぐらいの量になるので、ここでは、binaryコマンドで日本語を扱う場合に必要な注意点だけを説明します。

Tclでは8.1から内部コードにUnicodeを採用しているのですが、Unicodeを扱う上で注意することがあります。

UnicodeとUTF-8は違うものであるということをご存じでしょうか?

簡単に説明すると、UnicodeはU+XXXXで表記される文字集合のことで、UTF-8は、この文字集合を符号化したものになります。符号化方式には、UTF-7,UTF-8,UTF-16,UTF-32などが存在します。

例えば、
文字「あ」は、UnicodeではU+3042ですが、UTF-8ではE38182の3バイトのコードになります。

Tclのコマンド・マニュアルで、binaryコマンドのタイプ:a の項目をGoogleで翻訳してみると以下のようなことが記載されています。

[原文]
Every character is taken as modulo 256 (i.e. the low byte of every character is used, and the high byte discarded) so when storing character strings not wholly expressible using the characters \u0000-\u00ff, the encoding convertto command should be used first to change the string into an external representation if this truncation is not desired (i.e. if the characters are not part of the ISO 8859-1 character set.)

[和訳]
すべての文字はモジュロ256として扱われます(つまり、すべての文字の下位バイトが使用され、上位バイトは破棄されます)。

文字列\u0000 – \u00ffを使用して完全には表現できない文字列を格納する場合、この切り捨てが望ましくない場合(つまり、文字がISO 8859-1文字セットの一部でない場合)には、最初に文字列をencoding converttoコマンドを使って外部表現に変更しておく必要があります。

http://www.tcl.tk/man/tcl8.6/TclCmd/binary.htm#M17

モジュロ256(modulo 256)とは、256で割った余りを計算するという意味だそうです。引用の中の()で囲まれた文を含めて解釈すると、例えば、文字「あ」をバイナリデータに変換すると、UTF-8のバイナリデータ3バイトではなく、Unicodeであるu\3042の下位バイト、つまり\x42に相当するバイナリ値を返します。

ちなみに、U+0042は「B」になります。

例.

$ tclsh
% set n [binary format a* あ]
B

その次に記載されている内容(日本語では分かりにくい表現ですが)は、ASCIIコードの範囲外の文字を使用する場合、encoding converttoコマンドを使って、事前に変更しておく必要がありますよ。ということです。

例.

$ tclsh
% set n [binary format a* [encoding convertto utf-8 あ]]
あ
% binary scan $n H* str
1
% puts $str
e38182
encoding convertto ?encoding? string 

このコマンドは、stringをUnicodeから指定された、エンコーディングに変換します。

「あ」を「\u3042」と表記しても結果は同じです。

上の例の場合、変数nに格納されるデータは、「あ」のUnicodeである\u3042からUTF-8へ変換した値:\xe3\x81\x82に相当するバイナリ値が格納されます。

binary scan $n H* str

これは、変数nのバイナリ値を16進数表記の文字列に変換して変数strに格納しています。

それと、フィールドの指定を「binary format a*」ではなく、countを数値で指定すると以下の結果になります。

「binary format a1」の場合
 => e3

「binary format a3」の場合
 => e38182

「binary format a6」の場合
 => e38182000000

上記より日本語などのマルチバイト文字を扱う場合、countの指定は文字数ではなくバイト数(1バイト文字)としてカウントされています。


コメント

タイトルとURLをコピーしました