その後いろいろやってみて、ちょっとわかってきた。eucやjisに変換されなかった、丸数字や、IBM拡張文字は、euc/jisには存在しないようだ。だから、Encode.pmでは、その規格通り、マッピングしないという動作をしている。しかし、eucでもjisでも、Windowsなパソコンではそれらの文字は使えているので、何か方法があるのではと探していたら、Encode::EUCJPMSというモジュールがあった。
これをEncodeモジュールと一緒に使うと、
use strict; use utf8; use Encode::EUCJPMS; use Encode qw/encode decode/; my $internal = decode("cp932", $sjis); my $jis = encode("cp51220", $internal); my $euc = encode("eucJP-ms", $internal);
などのように、cp932の文字すべてを扱えるeuc/jisコードを扱えるようだ。素晴らしい。
ただし、このモジュールはXSを使うので、このサイトのように、サーバを選べない条件を想定したプログラムを書くときには選択肢として厳しいので、Encodeモジュールのencode()をUnicode::Japaneseに渡すラッパーになっているEncode::Unicode::Japaneseなどがとても便利と思ってしまう。PurePerlだし、全角チルダ問題なども処理されるので意識しないでコードが書ける。他にも全角半角変換などいろいろな機能が付いていて便利。しかしとても遅い。
use strict; use warnings; use utf8; use Encode::Unicode::Japanese; use Encode qw(encode decode); use Benchmark; my $fh; open($fh, "<", "sjis.txt"); my $sjis = join("", <$fh>); close($fh); my $internal = decode('cp932', $sjis); timethese(100000, { 'TEST1' => '&test1;', 'TEST2' => '&test2;', }); sub test1 { encode('eucjp', $internal); } sub test2 { encode('unijp-euc', $internal); }
を走らせたところ、
Benchmark: timing 100000 iterations of TEST1, TEST2... TEST1: 1 wallclock secs ( 0.98 usr + 0.00 sys = 0.98 CPU) @ 101626.02/s (n=100000) TEST2: 6 wallclock secs ( 5.83 usr + 0.03 sys = 5.86 CPU) @ 17064.85/s (n=100000)
となった。6倍かかっている。負荷が問題にならないケースではこっちを使いたい。もちろん他にも方法があると思うので引き続き調べることにする。
[参考ページ] isoya9の日記 - [perl]Encode Jcode Unicode::Japanese のベンチマーク比較