Perlの文字コード変換の話 其の参

○ PerlIO

Perl 5.6 以降からは「入力 -> Perl内部処理 -> 出力」の橋渡しをするためのレイヤーとして
PerlIO というものが存在している。

PerlIO に対して使用するエンコードを指定することができる。

PerlIOに文字コードが指定されている場合、utf8フラグの立っている文字列をPerlIOに
渡すと、内部で適切な文字コード変換が行われる。

次のコードでは、STDOUT にshiftjis を指定することで、出力結果としてshiftjisの
文字列が表示される

use utf8;
use Encode;
binmode( STDOUT, ':encoding(shiftjis)' );

my $a_data = "ほげほげ";
if( Encode::is_utf8( $a_data ) ){
print "utf8 on\n";
}else{
print "utf8 off\n";
}

print $a_data . "\n";

結果(shiftjisで表示されているものとする)

utf8 on
ほげほげ

ここで、binmode( STDOUT, ':encoding(shiftjis)' ) が STDOUT のPerlIOをshiftjisとして
扱う宣言である。

仮に、この部分をコメントアウトした場合、次のような結果となる。

Wide character in print at ./test2.pl line 13.
utf8 on
縺サ縺偵⊇縺楷

一行目の、"Wide character in print ..."という警告文は、utf8フラグの立っている文字列を
文字コードの指定されていない PerlIO に渡した場合に表示される警告文である。

この警告文については、後に詳しく説明する。

PerlIO に文字コードを指定していなかった場合、utf8フラグの立っていない文字列
(便宜上バイトエンコード文字列と呼ぶ)を渡す必要がある。

utf8フラグの立っている文字列を、バイトエンコード文字列に変換するためには、Encode
モジュールの Encode::encode() を利用する。

以下に、サンプルコードを示す

use utf8;
use Encode;
#binmode( STDOUT, ':encoding(shiftjis)' );

my $a_data = "ほげほげ";
if( Encode::is_utf8( $a_data ) ){
print "utf8 on\n";
}else{
print "utf8 off\n";
}

print "data = " . $a_data . " \n"; # 警告が出ている部分

my $a_byte_str = Encode::encode( 'shiftjis', $a_data );

if( Encode::is_utf8( $a_byte_str ) ){
print "utf8 on\n";
}else{
print "utf8 off\n";
}

print "byte = " . $a_byte_str . "\n";

実行結果は、次のようになる

Wide character in print at ./test2.pl line 15.
utf8 on
data = 縺サ縺偵⊇縺楷
byte = ほげほげ

このように Encode:encode() を用いることで、内部表現文字列をバイト文字列に変換
することが出来る。

ここでのポイントをまとめておくと

  • PerlIOに文字コードが指定されている場合には、内部表現文字列を渡す
  • PerlIOに文字コードが指定されている場合には、PerlIOが内部表現文字列を適切な形に変換する
  • PerlIOに文字コードが指定されていない場合には、バイト文字列を渡す

ということである。