Digest::SHAはマルチバイト文字列でも大丈夫だけどDigest::MD5だとエラーになる
同じDigest::*だと思ったら大間違いという話。
-MDigest::SHA=sha512_hexだと
use Digest::SHA qw/ sha512_hex /; use utf8; use Encode qw/ encode_utf8 /; print sha512_hex("あいうえお"),"\n"; #=> ed8ad6b03b7cb459... print sha512_hex(encode_utf8("あいうえお")),"\n"; #=> ed8ad6b03b7cb459...
動くし、同じ値になる。
use Digest::MD5 qw/ md5_hex /; use utf8; use Encode qw/ encode_utf8 /; print md5_hex("あいうえお"),"\n"; #=> Error: Wide character in subroutine entry at - line 5. print md5_hex(encode_utf8("あいうえお")),"\n"; #=> 86deb27a32903d...
マルチバイト文字は死ぬ。
ちゃんとpodにも書いてあった。
http://search.cpan.org/dist/Digest-MD5/MD5.pm
Perl 5.8 support Unicode characters in strings. Since the MD5 algorithm is only defined for strings of bytes, it can not be used on strings that contains chars with ordinal number above 255.
のでちょっとはまった。注意する。
2012/3/20 追記1
コメントいただきました。
「テキスト文字列(decoded string)はPerlの外にあるAPIに与えられない」という基本から考えるとむしろDigest::SHAのほうがおかしいと思います。 / “Digest::SHAはマルチバイト文字列でも大丈夫だけど…” htn.to/hsHvJh
— Fuji, Goroさん (@__gfx__) 3月 20, 2012
なるほど。
Authorが違うから実装も違ってるんでしょうか。
2012/3/20 追記2
URI::Escapeのuri_escapeもテキスト文字列だと死ぬ。
use URI::Escape; use utf8; print uri_escape("あいうえお"),"\n"; #=> Can't escape \x{3042}, try uri_escape_utf8() instead at - line 3
ただこっちは親切に「uri_escape_utf8()」を使えと言ってくれてる。
use URI::Escape; use utf8; print uri_escape_utf8("あいうえお"),"\n"; #=> %E3%81%82%E3%81%84%E3%81%86%E3%81%88%E3%81%8A
podにもあった。
The uri_escape() function will croak if given a characters with code above 255. Use uri_escape_utf8() if you know you have such chars or/and want chars in the 128 .. 255 range treated as UTF-8.