2011-08-11 51 views
1

我追逐的Perl代码,似乎根本上是这个版本中的错误:如何检测解码的字符串

"Cannot decode string with wide characters" appears on a weird place

基本上,在一定条件下,Encode::decode('utf8', $string)越做越同一调用两次字符串和欢闹随之而来。现在,最好的解决方案是找出导致双解码的条件,并停止发生。不幸的是,这是功能丰富的产品的成熟产品代码;弄清楚这些条件并以不会引入回归错误的方式修复它们看起来具有挑战性。

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

回答

1

编码具有is_utf8功能:

is_utf8(STRING [,CHECK])

[INTERNAL]测试的UTF8标志是否在STRING接通。 如果CHECK为真,还会检查STRING中的数据是否为格式正确的 UTF-8。如果成功则返回true,否则返回false。

注意,文件的标题是“Perl的内幕搞乱”,这个功能可能在将来的perl版本中改变。

+0

@BlairHippo,请注意,这与'utf8 :: is_utf8'完全相同,只是后者是内置的,这意味着您不需要加载任何模块来使用它。请记住,既不准确返回字符串是否已被解码。 – ikegami

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); 
    

你应该解码所有的输入和编码所有的输出。

+0

人们也可以搜索使用UTF-16,UCS-2和UTF-32/UCS-4编码的NUL字节或换行符,但这些都变得非常具体。 – ikegami