【问题标题】:How To Detect Decoded String如何检测解码的字符串
【发布时间】:2011-08-11 16:45:01
【问题描述】:

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

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

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

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

【问题讨论】:

    标签: perl utf8-decode


    【解决方案1】:

    无法正确检测标量是否包含已解码的字符串。没有办法将该信息传达给 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);
      

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

    【讨论】:

    • 也可以搜索使用 UTF-16、UCS-2 和 UTF-32/UCS-4 编码的 NUL 字节或换行符,但这已经非常具体了。
    【解决方案2】:

    Encode 有一个is_utf8 函数:

    is_utf8(STRING [, CHECK])

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

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

    【讨论】:

    • @BlairHippo,请注意,这与utf8::is_utf8 的作用相同,只是后者是内置的,这意味着您无需加载任何模块即可使用它。请记住,两者都不会准确返回字符串是否已被解码。
    猜你喜欢
    • 2013-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-31
    • 2021-12-19
    • 1970-01-01
    相关资源
    最近更新 更多