by Hippo2000(1999/4/23,7/13,
2000/3/12)
岡部さんがもっとシンプルかつ強力な変換ルーチンを提供していらっしゃいます。それも両方向!! こちらを見て下さいね。
http://www.geocities.co.jp/SiliconValley-PaloAlto/2514/
さらにJcode.pmでもUTF8の変換ができます。(こちらはCPANをご覧下さい)
XML::Parserを使おうとして、ハタと気が付いたことがあります。文字はUTF8で返ってくるのです。
UTF8って何さ?私はXMLで漢字も使いたいぞーというわけで、変換する方法を簡単にまとめてみました。
ここに載っているプログラム例では何ら保証しません。(というほどのものでもないですが)
XML::Parserモジュールでは文字はUTF8で返ってきます。半角英数字しか使わない人たちなら問題ないのでしょうけれど、日本人なら漢字は必須。なおかつ私はPCユーザというわけで、UTF8をシフトJISに変換したろうやないかと思ったわけです。
ただこの方法には問題があります。シフトJISとUnicodeのマッピングがベンダー毎に違っている部分があるのです。(今はUnicodeコンソーシアムのものを使用しています。それだけ、変換テーブルを用意するとかということもありますが。)
したがってあくまでも簡易な方法ということでとらえてください。本格的な話があるとすれば、UTF8にデコードしているのと反対のモジュールをお願いするのが一番近道かもしれません。(いかがなものでしょう?)
あらためて日本語の文字コード標準化が矛盾無い形で整理されることを望みます。
#JISの第3、4水準と呼ばれるであろうものも含めて
これまで教えて頂いたり、調べたりした結果UTF8をSJISを変換する方法には以下のようなものがありました。
(1)コマンドラインから使うプログラムで変換する(ex. ToolMan Editor、tcs未確認です)
(2)ActiveXを使う (ex. JavaComCharConv)
(3)Perlのプログラムを使う (ex. cjkvconv.pl)
(4)Perlのモジュールを使う (ex. Unicode, XML::Encode 未確認です).
教えていただいた榊原さん、佐郷さん、前寺さん、なかたにさん、どうもありがとうございました。
ただPerlプログラムの中で「関数」のように使いたいこと、tcsや(4)のモジュールはWin32にポートするのが大変なこと(私の環境にはコンパイラすら積んでないんです)があり、悩んだ末に(3)のソースを参考に自分なりに作ってみました。
まずUTF8は、ASCIIコードの範囲はそのままで、いわゆる全角文字は範囲はUnicode(UCS-2のほうが正しい表現かも)で、ビットをばらした形の3バイトで入っているということがわかりました。
そこで3バイトの文字を見つけたらUnicodeにし、さらにその文字を変換テーブルで変換するようにしてみました。
変換テーブルはUnicodeコンソーシアムの変換表を利用しています。(自分用には半角カナの対応のための部分も追加しています)
見せるのも恥ずかしいようなソースなのですが、ご参考までに載せます。間違っている点などありましたら、指摘して下さい。
#XMLの練習
use XML::Parser;
use Convutf8;
sub Tchar(\$$) {
my ($Exp, $cChar) =@_;
print &Utf8toSJIS($cChar);
}
my $parser = new XML::Parser(Handlers => {Char => \&Tchar});
$parser->parsefile($ARGV[0]);
|
use strict;
package ConvUTF8;
my(%sSjis, %sJis);
BEGIN {
my($sSJIS, $sJIS, $sUni);
open(IN, "<./jis0208.txt");
while(<IN>) {
next if(/^#/);
($sSJIS, $sJIS, $sUni) = split;
$sSjis{pack("H4", substr($sUni, 2))} = pack("H4", substr($sSJIS, 2));
}
close(IN);
}
sub ::Utf8toSJIS($) {
my ($uStr) = @_;
my($iPos, $sKey, $iLen);
my($sRes);
$iPos = 0;
$sRes = "";
for($iPos = 0;$uStr ne ""; $uStr = substr($uStr, $iLen)) {
if ($uStr =~ /^([\x00-\x7F])/) {
$iLen = 1;
$sRes .= $1;
} elsif ($uStr =~ /^([\xC0-\xDF])([\x80-\xBF])/) {
$iLen = 2;
$sRes .= pack("n",((ord($1) & 31) << 6) | (ord($2) & 63));
#または (下記注を参照)
#$sKey = pack("n",((ord($1) & 31) << 6) | (ord($2) & 63));
#$sRes .= $sSjis{$sKey};
} elsif ($uStr =~ /^([\xE0-\xEF])([\x80-\xBF])([\x80-\xBF])/) {
$iLen = 3;
$sKey = pack("n",((ord($1) & 15) << 12)| ((ord($2) & 63) << 6) | (ord($3 ) & 63));
$sRes .= $sSjis{$sKey};
} else {
die "Whoah! Bad UTF-8 data!$uStr\n";
}
}
return $sRes;
}
|
※ ここはUTF8では2バイトで表現される文字で、日本語では半角カナが対応するのだと
考えています。これらの行を加えるときには変換テーブルにも対応する文字の行を加えてください
鈴木紀夫さんから指摘を受けて加えました。(2000/3/12)
# Name: JIS X 0208 (1990) to Unicode # Unicode version: 1.1 # Table version: 0.9 # Table format: Format A ... (中略)... 0x8140 0x2121 0x3000 # IDEOGRAPHIC SPACE 0x8141 0x2122 0x3001 # IDEOGRAPHIC COMMA 0x8142 0x2123 0x3002 # IDEOGRAPHIC FULL STOP 0x8143 0x2124 0xFF0C # FULLWIDTH COMMA 0x8144 0x2125 0xFF0E # FULLWIDTH FULL STOP 0x8145 0x2126 0x30FB # KATAKANA MIDDLE DOT 0x8146 0x2127 0xFF1A # FULLWIDTH COLON 0x8147 0x2128 0xFF1B # FULLWIDTH SEMICOLON 0x8148 0x2129 0xFF1F # FULLWIDTH QUESTION MARK ... (後略)... |
<?xml version="1.0" encoding="x-sjis-unicode"?> <SAMPLE> **************************** *河馬屋二千年堂 * *漢字の練習123123 、 * *あいうえお、アイウエオ、 * * Sample.XMLです * **************************** </SAMPLE> |
C:\xml>perl p.pl test.xml **************************** *河馬屋二千年堂 * *漢字の練習123123 、 * *あいうえお、アイウエオ、 * * Sample.XMLです * **************************** C:\xml> |
この文書をつくるのにあたり、以下のサイトのお世話になりました.
JIS0208の対応表
ftp://ftp.unicode.org/Public/MAPPINGS/EASTASIA/JIS/JIS0208.TXT
http://www.piedey.co.jp/index.html JavaComCharConvのページ
http://hp.vector.co.jp/authors/VA002891/indexj.htm ToolManのページ
http://ftp.uni-mannheim.de/info/OReilly/nutshell/ujip/perl/cjkvconv.pl
ご意見、ご質問はこちらの掲示板で受け付けています。
またメールは河馬屋(Nifty)にお願いします。