我正在追逐Perl代码中的一个错误,似乎从根本上说是一个版本:
"Cannot decode string with wide characters" appears on a weird place
基本上,在某些条件下,Encode::decode('utf8', $string)
会在同一个字符串上被调用两次,并且随之而来的是欢闹。现在,最好的解决方案是找出导致双重解码的条件并阻止其发生。不幸的是,这是功能丰富的产品的成熟生产代码;找出这些条件并以不引入回归错误的方式修复它们看起来很有挑战性。
是否有一些快速可靠的方法来检测字符串是否已经从utf8解码?在这些调用之前插入“if”语句感觉有点笨拙,但应该是一个非常安全的解决方案。
答案 0 :(得分:5)
无法正确检测标量是否包含已解码的字符串。没有办法将这些信息传达给Perl,所以没有办法将它传达给你。人们可以猜测。您可以使用一些启发式方法。从最可靠到最不可靠:
如果字符串包含255以上的字符,则不进行编码。这正是导致“宽字符”警告/错误的原因。
utf8::encode($s) if /[^\x00-\xFF]/;
如果标量将使用UTF-8进行编码(如果它已编码且标量包含有效的UTF-8),则它可能已编码。
如果标量将使用UTF-8进行编码(如果它已编码且标量不包含有效的UTF-8),则可能已对其进行解码。
utf8::encode($s) if !utf8::decode(my $tmp = $s);
如果标量的UTF8
标志打开,则字符串可能已解码。
如果标量的UTF8
标志已关闭,则该字符串可能未被解码。
utf8::encode($s) if utf8::is_utf8($s);
您应解码所有输入并对所有输出进行编码。
答案 1 :(得分:1)
Encode具有is_utf8功能:
is_utf8(STRING [,CHECK])
[INTERNAL]测试是否在STRING中打开了UTF8标志。 如果CHECK为真,则还检查STRING中的数据是否格式正确 UTF-8。如果成功则返回true,否则返回false。
请注意,文档的标题是“与Perl的内部版本混淆”,此函数可能会在将来的perl版本中更改。