1

我正在追逐 Perl 代码中的一个错误,它似乎基本上是这个版本:

“无法解码带有宽字符的字符串”出现在一个奇怪的地方

基本上,在某些条件下,Encode::decode('utf8', $string)在同一个字符串上被调用两次,然后就会产生欢闹。现在,最好的解决方案是找出导致双重解码的条件并阻止这种情况发生。不幸的是,这是功能丰富的产品的成熟生产代码;找出这些条件并以不引入回归错误的方式修复它们看起来具有挑战性。

是否有一些快速可靠的方法来检测字符串是否已经从 utf8 解码?在这些调用之前插入“if”语句感觉有点笨拙,但应该是一个非常安全的解决方法。

4

2 回答 2

5

无法正确检测标量是否包含已解码的字符串。没有办法将该信息传达给 Perl,因此它无法将其传达给您。充其量,一个人可以猜到。您可以使用一些启发式方法。从最可靠到最不可靠:

  1. 如果字符串包含大于 255 的字符,则不会对其进行编码。这正是导致“宽字符”警告/错误的原因。

    utf8::encode($s) if /[^\x00-\xFF]/;
    
  2. 如果标量将使用 UTF-8 进行编码,并且标量包含有效的 UTF-8,则它可能已被编码。

  3. 如果标量将使用 UTF-8 进行编码,如果它已编码并且标量不包含有效的 UTF-8,则它可能已被解码。

    utf8::encode($s) if !utf8::decode(my $tmp = $s);
    
  4. 如果标量的UTF8标志打开,则字符串可能已解码。

  5. 如果标量的UTF8标志关闭,则字符串可能未解码。

    utf8::encode($s) if utf8::is_utf8($s);
    

您应该解码所有输入并编码所有输出。

于 2011-08-11T22:59:30.077 回答
1

Encode 有一个is_utf8函数:

is_utf8(字符串 [,检查])

[INTERNAL] 测试 STRING 中的 UTF8 标志是否打开。如果 CHECK 为真,还检查 STRING 中的数据是否为格式良好的 UTF-8。如果成功则返回 true,否则返回 false。

请注意,文档的标题是 “Messing with Perl's Internals”,这个功能可能会在未来的 perl 版本中改变。

于 2011-08-11T17:41:04.857 回答