読者です 読者をやめる 読者になる 読者になる

Perl日記

PerlとかRubyとかPHPとかPythonとか

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...

動くし、同じ値になる。


-MDigest::MD5=md5_hexだと

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

コメントいただきました。

なるほど。
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.

http://search.cpan.org/~gaas/URI-1.59/URI/Escape.pm