下記の『﨑』『鄧』『髙』の3文字は 現在は Unicode を使って表現できますが、 Shift_JIS には含まれない文字のため、 クライアント環境によっては表示できない場合は依然多く、文字化けしやすいです。
漢字 | CP932 | EUC-JP | UCS2 | UTF8 | 補足 |
---|---|---|---|---|---|
﨑 | FAB1 | - | FA11 | EFA891 | 山+立+可 |
鄧 | FBB9 | 8FE2C7 | 9127 | E984A7 | とう小平 |
髙 | FBFC | - | 9AD9 | E9AB99 | ハシゴ高 |
しかし HTML での利用においては、 最近のブラウザは &#xHHHH; 形式で Unicode のコード(UCS2)を指定すると、 クライアント側に該当フォントがあれば、表示できるようになります。
本ページでは、Perl+Jcode.pm を使って その自動変換を行うパッチをご紹介します。
Perl 5.8.x では、コード変換に標準モジュールの Encode.pm を利用できます。
Unicode (UTF-8) → Shift_JIS のコード変換を行う際に XMLCREF オプションを利用すると、 Unicode にあって Shift_JIS に含まれない文字が &#xHHHH; の形式に変換されます。
以下のサンプルでは、『﨑鄧髙』の3文字を UTF-8 から Shift_JIS に変換して表示しています。
#!/usr/bin/perl
use Encode;
my $text = "\xEF\xA8\x91\xE9\x84\xA7\xE9\xAB\x99";
Encode::from_to( $text, "UTF8", "Shift_JIS", Encode::XMLCREF );
print $text, "\n";
の実行結果は『﨑鄧髙』とエスケープされました。 この3文字は Shift_JIS には含まれないため、 Encode.pm によって Unicode 番号にエスケープされています。 もちろん、これ以外の通常の文字については、正しく Shift_JIS で出力されます。 また、
#!/usr/bin/perl
use Encode;
my $text = "\xEF\xA8\x91\xE9\x84\xA7\xE9\xAB\x99";
Encode::from_to( $text, "UTF8", "CP932", Encode::XMLCREF );
print $text, "\n";
のように、"Shift_JIS" でなく "CP932" を指定した場合は IBM 拡張文字のコードを利用できるため、 『﨑鄧髙』の文字をそのまま出力することもできます。
Perl 5.005 および Perl 5.6.1 では、Encode.pm モジュールが利用できないため、 コード変換は Jcode.pm を利用します。 Jcode.pm の内部コードは、JIS X 0212 に対応した EUC-JP になっています。 Unicode を Shift_JIS に変換する場合、 Unicode→EUC-JP→Shift_JIS と順に変換されます。
このとき、Unicode→EUC-JP の変換時には、 Unicode に表現できて EUC-JP で表現できない文字は『??』に変換されます。 また、EUC-JP→Shift_JIS 変換時には、 EUC-JP で表現できて Shift_JIS で表現できない文字は『〓』に変換されます。 (なぜ統一していないのかは分かりませんが、区別がつくのは便利ですね)
#!/usr/bin/perl use Jcode; my $text = "\xEF\xA8\x91\xE9\x84\xA7\xE9\xAB\x99"; Jcode::convert( \$text, "sjis", "utf8" ); print $text, "\n";
Encode::from_to と Jcode::convert では コードの指定順が逆なのに注意してください。
この結果は、『??〓??』となります。 まず『﨑』と『髙』は EUC-JP(JIS X 0212)で表現できないため、 『??』に変換されます。 対して『鄧』は EUC-JP では表現できますが、Shift_JIS(≠CP932)で表現できないため、 今度は『〓』に変換されます。
上記のような Shift_JIS 環境での文字化けは避けたいところですが、 Jcode.pm には、Encode.pm の XMLCREF のような便利なオプションがありません。 そこで Jcode.pm でも XMLCREF のように &#xHHHH; の形式にエスケープする パッチプログラムを作成しました。
下記の手順でパッチを適用・インストールします。
$ wget http://openlab.jp/Jcode/Jcode-2.00.tar.gz
$ wget http://www.kawa.net/works/jcode/jcode-xmlcref-20050117.patch
$ tar zxf Jcode-2.00.tar.gz
$ cd Jcode-2.00
$ patch -p0 < ../jcode-xmlcref-20050117.patch
$ perl Makefile.PL && make
# make install
このパッチを適用した Jcode.pm では、
がそれぞれ &#xHHHH; 形式にエスケープされます。同じ
#!/usr/bin/perl use Jcode; my $text = "\xEF\xA8\x91\xE9\x84\xA7\xE9\xAB\x99"; Jcode::convert( \$text, "sjis", "utf8" ); print $text, "\n";
を実行した結果は、『﨑鄧髙』となって エスケープされました。 もちろん、これ以外の通常の文字については、正しく Shift_JIS で出力されます。
Jcode.pm 1.99 以降のバージョンでは、 Jcode.pm の内部的に Encode.pm を利用するように変更されました。
Perl | Jcode.pm | 処理エンジン | 内部コード | 対応 |
---|---|---|---|---|
5.005〜5.8.0 | - | Jcode.pm独自 | EUC-JP | 本パッチを適用してください |
5.8.1〜 | 〜0.88 | Jcode.pm独自 | EUC-JP | 本パッチを適用してください |
5.8.1〜 | 1.99〜 | Encode.pm利用 | UTF-8 | fallback メソッドを利用してください |
Perl 5.8.1 以降と組み合わせた場合、fallback メソッドが利用できるため、 本パッチの利用は不要になります。(適用しても無視されます)
my $text = "\xEF\xA8\x91\xE9\x84\xA7\xE9\xAB\x99"; my $j = jcode($text); $j->can("fallback") and $j->fallback(Jcode::FB_XMLCREF()); my $sjis = $j->sjis;
このように記述することで、
Perl 5.8.1 以降では
Enccode.pmでXMLCREF
を指定したのと同じ効果を得られます。
ただし、Perl 5.8.1 未満を利用した場合は、fallback メソッドは利用できないため、
効果はありません。(本パッチの適用が必要です)
トラックバックURL:http://www.kawa.net/service/tb/ajaxtb.cgi/works/jcode/uni-escape.html
Kawa.netxp © Copyright 2004-2006 Yusuke Kawasaki