« 乱数の信憑性 | メイン | TEST »

文字と文字コード

コンピューターというのは、基本的にデジタル処理(1と0、ONとOFFなど)しかできないので、文字の形をそのまま覚えるとかなりの容量が必要になる。それで、容量を減らすために文字に番号をつけて覚えておいて、番号を復元することで文字として読めるようになっている。その番号の付け方が、日本語なら「SJIS」や「EUC」、「JIS」などという規格で決められているので、「SJIS」として記録してるデータは「SJIS」で復元しないと意味不明な記号の羅列に見えてしまう。

まあ、その辺の詳しい(もしくは、正確な)事は「文字コード」とか「漢字コード」で検索すればいろいろと見つかるでしょう。2つほどあげれば、「日本語と文字コード」や「文字コードの話」などでしょうか。

結局何が言いたいかというと、フォームから送信されたデータで「%」がついてる(例えば「%82%A0%82%A2%82%A4%82%A6%82%A8」のような)ものは、URLに使えない(使うのを推奨されていない)文字の「文字コードを“%”付の文字列に変換」した結果、だという事。「フォームからの入力」で意味不明な状態で使っていた「pack()」の命令は、「“%”付の文字列を文字コードに変換」している作業だ。

・・・なんか、前置きが長くなったかも・・・。

で、今回やりたかったのは、「文字←→文字コード」の変換。でも、Perlにはそれ専用の関数があったりする。「文字→文字コード」にするのが「ord()」で、「文字コード→文字」にするのが「chr()」だ。ただ「ord()」は1バイト分しか変換できないようで、複数の文字とか全角をいれると最初の1バイトだけを変換して返すようだ。配列で受けてもデータが1個しかない。

ところで、1バイトというのは8ビット、つまり、8桁の2進数の事で、256個の情報を区別する事ができる。8桁の2進数は16進数で表すと2桁になる。人間でもこの変換は比較的簡単なので、この手のデータの表現には16進数を使う事が多い。

01011010 → 0101 1010 → 8*0+4*1+2*0+1*1 8*1+4*0+2*1+1*0 → 5 A(10) → 5A
むぅ。なんか話がずれてる・・・。

で、結局何かというと、「ord()」を使うなら1バイトずつ区切る必要があるということ。そして、1バイト毎にデータ化するなら16進数が便利ということ。

ただ、「ord()」は数値で返ってくるので、16進数に変換する必要がある。そして「chr()」は数値に変換してやらなくてはいけない。しかも、それぞれ1バイトずつなのでループが大変・・・。

実は「unpack()」や「pack()」の添え字(?)に「H」を使う事で「文字コードを16進数の文字列に変換する(またはその逆)」ことができる。これらは1バイトずつ区切らなくてもいいので、全体を変換するのはとても簡単。

・・・まあ、最終的にはこれが書きたかったんだけど、すごくまわりくどい書き方になった。

この「pack()」の添え字「H」を使う方法は「Perlメモ」の「URIエスケープ・アンエスケープする」を見て知りました。他にもいろんな事が書いてあります。しかも実用的なコードでまとめられているので応用も簡単にできます。もし知らなかったのなら行ってみましょう。

ソースコード

#!/usr/bin/perl
 
#BEGIN{
#	print "Content-type: text/plain\n\n";
#	open(STDERR, ">&STDOUT");
#	$|=1;
#}
 
$usr_title = 'テスト32';
 
$tgCode = ord('漢');
if($tgCode == 0x8a){
	$usr_outcode = 'sjis';
}elsif($tgCode == 0xb4){
	$usr_outcode = 'euc';
}
 
require "./tsenv.pl";
 
{
	printHeader($usr_title);
	printBodyHeader('文字←→文字コード');
 
# チェックする文字
	@checkStrs = ('a', 'A', '1', '@', '\\', '}', '[ ]', 'あ');
 
# 1文字変換
	Jprint(<<EOM);
<table border=1>
<caption>ord() &amp; chr()</caption>
<tr>
<th rowspan=2>文字
<th rowspan=2>→
<th colspan=5>文字コード
<th rowspan=2>→
<th rowspan=2>文字
</tr>
 
<tr>
<th>10進数
<th>→
<th>16進数
<th>→
<th>10進数
</tr>
 
EOM
 
	foreach(@checkStrs){
		my $dOrd  = ord();
		my $hOrd  = sprintf("%x", $dOrd);
		my $dhOrd = hex($hOrd);
		my $dChr  = chr($dhOrd);
		print <<EOM;
<tr>
<td>$_
<td>
<td>$dOrd
<td>
<td>$hOrd
<td>
<td>$dhOrd
<td>
<td>$dChr
</tr>
 
EOM
 
	}
 
	Jprint(<<EOM);
</table>
EOM
 
# 一括変換その2
	push @checkStrs, '漢字', 'Nobu3', '!"#()=~';
 
	Jprint(<<EOM);
<table border=1>
<caption>unpack(H*) &amp; pack(H*)</caption>
<tr>
<th>文字
<th>→
<th>文字コード
<th>→
<th>文字
</tr>
 
EOM
 
	foreach(@checkStrs){
		my $hunpack = unpack("H*", $_);
		my $hpack = pack("H*", $hunpack);
		print <<EOM;
<tr>
<td>$_
<td>
<td>$hunpack
<td>
<td>$hpack
</tr>
EOM
 
	}
 
	Jprint(<<EOM);
</table>
EOM
 
	printFooter();
 
	exit(0);
}

カテゴリ:

トラックバック

このエントリーのトラックバックURL:

同一カテゴリの最新記事

最近のエントリー

Amazon.co.jp

Creative Commons License
このブログは、次のライセンスで保護されています。 クリエイティブ・コモンズ・ライセンス.
Powered by
Movable Type 3.36
Amazon.co.jp