Perlのutf8についてとか
さっきのエントリでバイト列がUTF8な文字列として認識されないとか言ってたんだけど無事できたー。
まぁさっきのエントリに追記してもいいんだけどPerlのエンコードがらみのことはよく分かってないので別エントリとしてメモ。
まず、さっきのエントリの解答。
#!/usr/bin/env perl use strict; use warnings; use Carp; sub assert { croak unless $_[0]; } # なくても結果は同じ。 # utf8::decode()使うのに必要かと思ったけど # シンボルパッケージテーブル見たら # デフォルトでuseされてるみたい? use utf8; sub bytes_str_to_utf8 { my $bytes = shift; # http://d.hatena.ne.jp/Gemma/20090617/1245266779より。 # どっちでも同じだけど後者の方が断然スマート。。。 # $bytes =~ s{(..)}{ # pack 'C', hex($1) & 0xff # }exg; $bytes = pack 'H*', $bytes; # バイト列をutf8な文字列として認識する。 utf8::decode($bytes); return $bytes; } my $bytes_str = "e4bba5e4b88be381aee69687e5ad97e58897e381af5554462d38e38292e69687e5ad97" . "e382a8e383b3e382b3e383bce38387e382a3e383b3e382b0e5bda2e5bc8fe381a8e381" . "99e3828b3136e980b2e695b0e381aee38390e382a4e38388e58897e381a7e38182e3828be38082"; assert(length($bytes_str) % 2 == 0); { local $\ = "\n"; # これをしてないと # 255より文字コードがでかいと # Wide character in 'print'と言われる。 # この適用範囲はこのブロックを外れてからも続く。 binmode STDOUT, ":utf8"; my $utf8_str = bytes_str_to_utf8($bytes_str); print $utf8_str; print length $utf8_str; # 文字数 print do { use bytes; length $utf8_str }; # バイト数 print "is utf8?:" . utf8::is_utf8($utf8_str); }
出力結果
以下の文字列はUTF-8を文字エンコーディング形式とする16進数のバイト列である。 41 109 is utf8?:1
バイト列をUTF8の文字列として認識するにはutf8::decode($bytes)をする必要があるらしい。
あとちょっとしたことだけどutf8::decode($bytes)は何故か1を返す。
(decode、encodeがちょっとごっちゃになってたんだけども、弾さんが
「入力した文字列はEncode::decode(入ってきた文字列のエンコード, 文字列)、
出力するときはEncode::encode(出力するエンコード, 文字列)」
と言ってたのをかろうじて思い出した)
binmodeについてはまた別エントリで書くとして、
とりあえずutf8.pmとbytes.pmの違いみたいなサンプルコードを勉強のために書いてみたので貼っておく。