UTF8をシフトJISに変換する

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で漢字も使いたいぞーというわけで、変換する方法を簡単にまとめてみました。

ここに載っているプログラム例では何ら保証しません。(というほどのものでもないですが)

 


目次

1. 背景

2. 変換する方法

3. プログラム例

参考資料


1.背景

XML::Parserモジュールでは文字はUTF8で返ってきます。半角英数字しか使わない人たちなら問題ないのでしょうけれど、日本人なら漢字は必須。なおかつ私はPCユーザというわけで、UTF8をシフトJISに変換したろうやないかと思ったわけです。

ただこの方法には問題があります。シフトJISとUnicodeのマッピングがベンダー毎に違っている部分があるのです。(今はUnicodeコンソーシアムのものを使用しています。それだけ、変換テーブルを用意するとかということもありますが。)

したがってあくまでも簡易な方法ということでとらえてください。本格的な話があるとすれば、UTF8にデコードしているのと反対のモジュールをお願いするのが一番近道かもしれません。(いかがなものでしょう?)

あらためて日本語の文字コード標準化が矛盾無い形で整理されることを望みます。
#JISの第3、4水準と呼ばれるであろうものも含めて

2. 変換する方法

これまで教えて頂いたり、調べたりした結果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)のソースを参考に自分なりに作ってみました。

3. プログラム

まずUTF8は、ASCIIコードの範囲はそのままで、いわゆる全角文字は範囲はUnicode(UCS-2のほうが正しい表現かも)で、ビットをばらした形の3バイトで入っているということがわかりました。

そこで3バイトの文字を見つけたらUnicodeにし、さらにその文字を変換テーブルで変換するようにしてみました。
変換テーブルはUnicodeコンソーシアムの変換表を利用しています。(自分用には半角カナの対応のための部分も追加しています)

見せるのも恥ずかしいようなソースなのですが、ご参考までに載せます。間違っている点などありましたら、指摘して下さい。

(1)プログラムの本体

#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]);                   

(2)変換するモジュール

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)
  

(3)変換テーブル(ftp://ftp.unicode.org/Public/MAPPINGS/EASTASIA/JIS/JIS0208.TXT )

#    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
... (後略)...                  

(4)元データ

<?xml version="1.0" encoding="x-sjis-unicode"?>
<SAMPLE>
****************************
*河馬屋二千年堂            *
*漢字の練習123123   、  *
*あいうえお、アイウエオ、  *
*  Sample.XMLです          *
****************************
</SAMPLE>        

(5)実行結果

C:\xml>perl p.pl test.xml                      

****************************
*河馬屋二千年堂            *
*漢字の練習123123   、  *
*あいうえお、アイウエオ、  *
*  Sample.XMLです          *
****************************

C:\xml>

参考資料

この文書をつくるのにあたり、以下のサイトのお世話になりました.

http://www.unicode.org/

JIS0208の対応表

ftp://ftp.unicode.org/Public/MAPPINGS/EASTASIA/JIS/JIS0208.TXT

http://www.piedey.co.jp/index.html  JavaComCharConvのページ

http://www.asahi-net.or.jp/~dp8t-asm/java/ のUTF8のページ

ftp://plan9.bell-labs.com/plan9/unixsrc/

http://hp.vector.co.jp/authors/VA002891/indexj.htm ToolManのページ

http://ftp.uni-mannheim.de/info/OReilly/nutshell/ujip/perl/cjkvconv.pl


ホーム Perlの小技

ご意見、ご質問はこちらの掲示板で受け付けています。
またメールは河馬屋(Nifty)にお願いします。