{ブロック}の外でのみ use utf8; したいのだが・・・
連投申し訳ありません。
「まるごとPerl」(2006年9月、インプレス刊)という本の「まるごとEncode」という記事に従ってEncodeの勉強をしています。
原記事は UNIX(というか端末コードをUTF-8に出来る環境)ですが、それをWindowsに移植しようとして苦労しています。
#! perl
# list3 -- UTF-8モードとバイトモードの切り替え
# インデントを表現するために全角空白を使っています
use strict;
use warnings;
binmode STDOUT, ':encoding(cp932)'; # 追加
# ブロックの外側ではUTF-8文字単位で解釈される
use utf8;
{
# ブロックの外側ではバイトモードが強制される
use bytes;
my $text = '漢字、カタカナ、ひらがなの混じったtext';
print Encode::decode('UTF-8', substr($text, 9, 12)); # カタカナと表示されたい
}
my $text = '漢字、カタカナ、ひらがなの混じったtext';
print substr($text, 3, 4); # カタカナと表示されたい
__END__
というプログラムを実行すると
C:\>list3.pl
カタカナカタカナ
と表示されてほしいのですが、
C:\>list3.pl
Cannot decode string with wide characters at C:/strawberry/perl/lib/Encode.pm li
ne 174.
と表示されます。
use utf8 を後ろにズラして
#! perl
# list3 -- UTF-8モードとバイトモードの切り替え
# インデントを表現するために全角空白を使っています
use strict;
use warnings;
binmode STDOUT, ':encoding(cp932)'; # 追加
{
# ブロックの外側ではバイトモードが強制される
use bytes;
my $text = '漢字、カタカナ、ひらがなの混じったtext';
print Encode::decode('UTF-8', substr($text, 9, 12)); # カタカナと表示されたい
}
# ブロックの外側ではUTF-8文字単位で解釈される
use utf8; # 移動
my $text = '漢字、カタカナ、ひらがなの混じったtext';
print substr($text, 3, 4); # カタカナと表示されたい
__END__
とするとうまく動いて
C:\>list3.pl
カタカナカタカナ
と表示されます。
#! perl
# list3 -- UTF-8モードとバイトモードの切り替え
# インデントを表現するために全角空白を使っています
use strict;
use warnings;
binmode STDOUT, ':encoding(cp932)'; # 追加
# ブロックの外側ではUTF-8文字単位で解釈される
use utf8;
my $text = '漢字、カタカナ、ひらがなの混じったtext'; # 移動
print substr($text, 3, 4); # カタカナと表示されたい # 移動
{
# ブロックの外側ではバイトモードが強制される
use bytes;
my $text = '漢字、カタカナ、ひらがなの混じったtext';
print Encode::decode('UTF-8', substr($text, 9, 12)); # カタカナと表示されたい
}
__END__
のようにするとやはり最初と同じエラーになりますが、
#! perl
# list3 -- UTF-8モードとバイトモードの切り替え
# インデントを表現するために全角空白を使っています
use strict;
use warnings;
binmode STDOUT, ':encoding(cp932)'; # 追加
# ブロックの外側ではUTF-8文字単位で解釈される
use utf8;
my $text = '漢字、カタカナ、ひらがなの混じったtext'; # 移動
print substr($text, 3, 4); # カタカナと表示されたい # 移動
no utf8; # 追加
{
# ブロックの外側ではバイトモードが強制される
use bytes;
my $text = '漢字、カタカナ、ひらがなの混じったtext';
print Encode::decode('UTF-8', substr($text, 9, 12)); # カタカナと表示されたい
}
__END__
だと大丈夫です。
結果として、ブロックの外で use utf8;、中では use bytes; という記事の著者の意図通りに動作しないようで、ブロックの中まで use utf8; が効いているようです・・・。
これは Perl の実装が変わったのでしょうか。
使用しているのは Windows XP Home SP3+Strawberry Perl v5.10.0 です。
補足
返信が遅くなりました。 >>きちんとBOMをつけて吐き出してもらわないと >>どうにもならないので,BOMがついてるという前提で. もったいぶった書き方をしましたが、adduseres.exe とかいう Windowsに添付のツールがありますが、これを /d:u オプション付きで 実行した結果、作成されるログ(テキスト)ファイルです。 >>Encode::Unicode -- Various Unicode Transformation Formats >>のマニュアルをご覧ください. マニュアルをネット検索して、読んでみました。 Encode::Unicodeのモジュールを別途追加(ppm)してやる必要があるということでしょうか。 (生半可知識で恐縮ですが) >>なお,nkfの新しいもの(v.2以降かな)ならUTF16LE,UTF16BEとかを >>きちんと変換したくれたように記憶しています. 結果的に他のツールですが、utf16→8へ変換してくれるフリーソフトが ありましたので、それをワンクッション入れて、その後、Encodeで UTF-8→Sjisへ変換するというベタな処理にして、現状はしのいでいます。 ノド元過ぎれば、これ以上手を打たないようになってしまいますが、 方法としては、ちょっとイマイチかなと感じております。