文字コード変換

今回はPerl/CGIプログラムで、指定した文字の文字コードを調べる方法と、その文字をShiftJisコードやEUCコード、UTF-8コードに簡単に変換する方法を解説します。

Perl/CGIプログラムでソフトウェアを開発する際、何らかの文字やデータを入力し、処理した結果を特定の形で出力するという流れがほとんどではないでしょうか。

特にPerl言語の性質上、入力データは文字を扱うことが多いと思います。

しかしPerl/CGIプログラムというのは、日本で開発されたわけではないので、日本語文字はもちろん、全角文字で表現されるアルファベットや記号を扱うときには注意が必要です。

もし、入力データの文字コードを適切に処理することができなかった場合には、Perl/CGIプログラムの誤動作の原因になったり、文字化けが発生してしまいます。

以前Perl/CGIプログラミング入門講座で、日本語文字を扱う際の注意点を書きましたので、そちらも参考にしていただければと思います。

文字コードの特定

Perl/CGIプログラム側で、入力されたり読み込んだ文字データの文字コードを調べたり、扱いやすい文字コードに変換することは簡単なんですが、もし利用条件が限られているのならば、これらの処理は必要ない場合があります。

必要ないのであれば当然、その処理をスキップすることができるので、結果Perl/CGIプログラムの実行速度が速くなります。

Perl/CGIプログラムの処理速度を上げるとなると難しそうだと感じるかもしれませんが、実はそんなことはありません。

例えば、テキストファイルを読み込んで表示させるPerl/CGIプログラムがあったとします。

仮に毎回読み込むテキストファイルは違っていたとしても、テキストファイルがすべてShiftJisコードと決まっていれば、Perl/CGIプログラム側で読み込んだテキストファイルの文字コードを調べる必要はありません。

このページを読んでいる人のほとんどは、Perl/CGIプログラムをインターネットサーバーに設置して、運用したいと思っているはずです。

その場合、Perl/CGIプログラムに入力される文字データの文字コードを特定できないんじゃないかと思われるかもしれませんが、そんなことはありません。

それでは、インターネットサーバー上でPerl/CGIプログラムを動かす場合について、具体例を挙げて考えてみましょう。

わかりやすいところで、このサイトでも作り方を1から解説し、サンプルスクリプトまで公開している、自動メール返信CGIを例にして考えてみましょう。

すでにわかっているとは思いますが念のために説明すると、自動メール返信CGIというのは、フォームメールCGIとも呼ばれており、お問い合わせページなどの入力フォームに入力された電子メールアドレス宛に、電子メールを送信するソフトウェアです。

このサイトでも、お問い合わせページで使っています。

このサイトで配布している自動メール返信CGIのサンプルスクリプトとその解説を見ていただければわかると思いますが、あの自動メール返信CGIはいろいろな環境で使用できるようにするため、フォームから入力されたデータの文字コードを調べ、プログラムが処理しやすい文字コードに変換しています。

そのため入力フォームもShiftJisコード、EUCコードとUTF-8コードのものの3種類用意しています。

なぜ3種類のフォームを用意したのかというと、これは自動メール返信CGIを設置するいろいろなウェブページの文字コードに対応するためです。

当然ですが、設置するウェブページと同じ文字コードの入力フォームしか使えません。

なので、ShiftJisコード、EUCコードとUTF-8コードの3種類の文字コードに対応した入力フォームを用意していても、ほとんどの場合、使うのは1種類になると思います。

昔はShiftJisコードのページが主流でしたが、今はワードプレスやムーバブルタイプといったコンテンツマネージメントシステムが作り出すウェブページがUTF-8コードのため、UTF-8コードのウェブページが主流になっています。

ちなみにこのサイトの文字コードもUTF-8コードです。

ここで文字コードの基本について説明しておきますとですね、入力フォームからPerl/CGIプログラムに送られるデータの文字コードというのは、入力フォームが設置されているページの文字コードになります。

つまり、このサイトのようにUTF-8コードを採用しているウェブページの場合は、お問い合わせページにあるHTMLの入力フォームもUTF-8コードで、そこに入力し自動メール返信CGIに送られる入力文字などのデータもUTF-8コードになります。

なので、あの自動メール返信CGIに速さを求めるのであれば、入力フォームから送られてくるデータは常にUTF-8コードと分かっているわけですから、入力データの文字コードを調べるプロセスは必要ないことになるわけです。

そして、あの自動メール返信CGIスクリプトは、ShiftJisコードで書かれているので、同じShiftJisコードに変換するだけで済みます。

中級レベルになると、自動メール返信CGIスクリプト自体もUTF-8にして、スクリプトを修正しさらにPerl/CGIプログラムの処理速度を上げるんですが、そこまでやると初心者がついてこれなくなるので、このサイトではやりません。

文字コードを調べる

Perl/CGIプログラムで文字コードを調べる方法について説明します。

以下のPerl/CGIスクリプトを見てください。

#!/usr/bin/perl

use strict;
use Jcode;

my $sjis_string = "\x83\x65\x83\x58\x83\x67";
my $euc_string = "\xA5\xC6\xA5\xB9\xA5\xC8";
my $utf8_string = "\xE3\x83\x86\xE3\x82\xB9\xE3\x83\x88";

print "Content-type: text/html; charset=shift_jis\n\n";
foreach my $string ($sjis_string, $euc_string, $utf8_string) {
my $charcode = &Jcode::getcode($string);
print $charcode, "<br>\n";
}
exit;

文字コードを調べるPerl/CGIスクリプトです。

実行結果はここをクリックすると確認できます。

変数「$sjis_string」にはShiftJisコード、「$euc_string」にはEUCコード、「$utf8_string」にはUTF-8コードの文字列をそれぞれ代入します。

「\x」からはじまっているのは、文字を16進数で表現しているからで、文字を16進数に変換するには16進変換ツールを使います。

逆に16進表現から文字に戻すときは、以下のように直接「print」命令で出力してやればわかります。

#!/usr/bin/perl

use strict;

print "Content-type: text/html; charset=shift_jis\n\n";
print "\x83\x65\x83\x58\x83\x67";
exit;

実行結果はここをクリックすると確認できます。

これでShiftJisコード、EUCコードとUTF-8コードの3種類の文字コードを、ひとつのPerl/CGIスクリプト上に書き込んでいます。

次に、文字コードをチェックしている部分についてみていきましょう。

わかりやすくするために1回ずつ丁寧に文字コードを調べてもいいんですが、それだと同じようなことを3回も書かなくてはいけなくなり面倒なので、foreachループを使って、文字コードを調べる命令文の記述を1回にしています。

でも実際に文字コードのチェックは、3回行われます。

実際に文字コードを調べているところは、「my $charcode = &Jcode::getcode($string);」という部分です。

「&Jcode::getcode」は、Jcodeモジュール内の関数を呼んでいますから、事前に「use Jcode;」でJcodeモジュールを読み込んでおくことをお忘れなく。

やっていることは、変数「$string」内の文字または文字列の文字コードを調べて、その結果を変数「$charcode」に代入しています。

Perl/CGIプログラムの実行結果を見てもわかるように、ShiftJisコードは「sjis」、EUCコードは「euc」、UTF-8コードの場合は「utf8」という文字列が代入されます。

文字コード変換

Perl/CGIプログラムで、ある文字コードを別の文字コードに変換してみます。

以下のPerl/CGIスクリプトを見てください。

#!/usr/bin/perl

use strict;
use Jcode;

my $sjis_string = "\x83\x65\x83\x58\x83\x67";
my $euc_string = "\xA5\xC6\xA5\xB9\xA5\xC8";
my $utf8_string = "\xE3\x83\x86\xE3\x82\xB9\xE3\x83\x88";

print "Content-type: text/html; charset=shift_jis\n\n";
foreach my $string ($sjis_string, $euc_string, $utf8_string) {
my $charcode = &Jcode::getcode($string);
&Jcode::convert(\$string, "sjis", $charcode) if ($charcode !~ /sjis/i);
print $string, "<br>\n";
}
exit;

実行結果はここをクリックすると確認できます。

文字コードを調べるところまでは、最初に提示しましたPerl/CGIスクリプトと同じです。

実際に文字コードを変換しているのは「&Jcode::convert(\$string, "sjis", $charcode) if ($charcode !~ /sjis/i);」という部分ですね。

すでに、ShiftJisコードは「sjis」、EUCコードは「euc」、UTF-8コードの場合は「utf8」という文字列が代入されることはわかっています。

なのでif文パターンマッチを使って、ShiftJisコードを表す文字列「sjis」以外だったらif文が成立し、文字コード変換が行われるようにしています。

文字コードを変換する「&Jcode::convert」関数の引数について説明します。

第1引数には、実際に文字コードを変更したい文字列を格納した変数をリファレンス形式で指定します。

第2引数には、変換したい文字コードを示す文字列を示します。

第3引数には、現在の文字コード(第1引数の文字列の文字コード)を表している文字列を指定します(省略可能)。

第2と3引数の各文字コードを表す文字列は、前述の文字コードを調べたときの戻り値と同じ形式の文字列が使えます。

つまり、ShiftJisコードは「sjis」、EUCコードは「euc」、UTF-8コードの場合は「utf8」ということです。

最後に、確認のためすべての文字列を表示してPerl/CGIプログラム終了です。