このアーカイブは同期化されません。 mixi の日記が更新されても、このアーカイブには反映されません。
文字コード変換をファイルハンドルに組み込んでみよう。
ファイルハンドルクラスには、
変換を行いながら出力を行うことになるので、
最低限 3 つの引数が必要だ。
・実際の出力先ファイルハンドル
・入力の文字コード
・出力の文字コード
引数は、連想配列(ハッシュ)を使って渡すことにしよう。
プログラムの見た目がすっきりするからだ。
使い手が以下のように呼び出せるように作ってみよう。
tie *OUT, 'EncoderHandle',
'IF_ENCODING' => 'euc-jp',
'IO_ENCODING' => 'shift_jis',
'HANDLE' => *STDOUT;
IF_ENCODING はプログラムの文字コード、
IO_ENCODING は、変換後の文字コード、
HANDLE は、実際にデータを書き出すファイルハンドルだ。
# 独自クラス。
package EncoderHandle;
# 今日は Encode を使う
use Encode;
# Tie::Handle を継承。
use Tie::Handle;
our @ISA = ('Tie::Handle');
# tie 関数に対応してオブジェクトを作成する。
# パラメータのチェックなどは省略。
sub TIEHANDLE {
my $package = shift;
my %param = @_;
bless(\%param, $package);
}
# 書き出し系関数のハンドラ。 引数は順に、
# インスタンス自身、データ、長さ、
# そして省略可能な、データ内の書き出し開始位置だ。
sub WRITE {
# 分かりやすいように引数を変数に格納。
my $this = $_[0];
my $length = $_[2];
my $offset = ($_[3] or 0);
my $text = substr($_[1], $offset, $length);
my $handle = $this->{'HANDLE'};
my $if_enc = $this->{'IF_ENCODING'};
my $io_enc = $this->{'IO_ENCODING'};
# コード変換。
my $length = Encode::from_to($text, $if_enc, $io_enc);
# 失敗すれば死ぬ。
die "Can't convert encoding" if not defined $length;
# 変換したデータを書き出す
print $handle $text;
}
# メインのパッケージに戻る。
package main;
# tie を呼び出して、OUT に割り付ける。
tie *OUT, 'EncoderHandle',
'IF_ENCODING' => 'euc-jp',
'IO_ENCODING' => 'shift_jis',
'HANDLE' => *STDOUT;
# print, printf などのために選択しておく。
select(OUT);
print 'Print', 'Some', 'String', "\n";
printf "%s=%d\n", 'Value', 1234;
syswrite OUT, 'syswrite!', 9;