【问题标题】:Check valid string encoding with PHP's intl (ICU) features使用 PHP 的 intl (ICU) 功能检查有效的字符串编码
【发布时间】:2011-07-08 15:53:29
【问题描述】:

使用 ICU 的 PHP intl 包装器中当前可用的功能,您将如何检查字符串编码的有效性? (例如检查有效的 UTF-8)

我知道它可以用 mbstring、iconv() 和 PCRE 来完成,但我对这个问题特别感兴趣。

【问题讨论】:

  • 您可以将其转换为 UCS4 并返回,看看是否有错误。如果您有有效的 UTF8,这是一个完全可逆的过程。这可能不是最快的解决方案,但除非您检查兆字节的数据,否则应该没问题。
  • 我希望这会奏效。但它是 intl 的哪一部分呢? php.net/manual/en/book.intl.php

标签: php unicode icu


【解决方案1】:

从 PHP 5.5 开始可以使用 UConverter。手册不存在。有关 API,请参阅 https://wiki.php.net/rfc/uconverter

function replace_invalid_byte_sequence($str)
{
    return UConverter::transcode($str, 'UTF-8', 'UTF-8');
}

function replace_invalid_byte_sequence2($str)
{
    return (new UConverter('UTF-8', 'UTF-8'))->convert($str);
}

function utf8_check_encoding($str)
{
    return $str === UConverter::transcode($str, 'UTF-8', 'UTF-8');
}

function utf8_check_encoding2($str)
{
    return $str === (new UConverter('UTF-8', 'UTF-8'))->convert($str);
}

// Table 3-8. Use of U+FFFD in UTF-8 Conversion
// http://www.unicode.org/versions/Unicode6.1.0/ch03.pdf)
$str =  "\x61"."\xF1\x80\x80"."\xE1\x80"."\xC2"."\x62"."\x80"."\x63"
    ."\x80"."\xBF"."\x64";
$expected = 'a���b�c��d';

var_dump([
    $expected === replace_invalid_byte_sequence($str),
    $expected === replace_invalid_byte_sequence2($str)
],[
    false === utf8_check_encoding($str),
    false === utf8_check_encoding2($str)
]);

【讨论】:

    【解决方案2】:

    我做了一些挖掘并找到了ICU unorm2_normalize() documentation。它的 pErrorCode out 参数很有趣。标准 ICU 错误代码从 utypes.h 的第 620 行开始。所以我尝试了这个测试脚本:

    $s = 'tête-à-tête';
    echo "normalizer_normalize(\$s) >> " 
         . var_export(normalizer_normalize($s), 1) . "\n";
    $s = "\xFF" . $s;
    echo "normalizer_normalize(\$s) >> " 
         . var_export($r=normalizer_normalize($s), 1) . "\n";
    if ($r===false)
        echo "normalizer_normalize() error: " 
             . intl_get_error_message() . "\n";
    // which outputs:
    normalizer_normalize($s) >> 'tête-à-tête'
    normalizer_normalize($s) >> false
    normalizer_normalize() error: Error converting input string to UTF-16: U_INVALID_CHAR_FOUND
    

    所以我想基于此的测试并寻找以下三个错误代码将是 UTF-8 编码错误的一个很好的迹象:

    U_INVALID_CHAR_FOUND 字符转换:不可映射的输入序列。 U_TRUNCATED_CHAR_FOUND 字符转换:输入序列不完整。 U_ILLEGAL_CHAR_FOUND 字符转换:非法输入序列/输入单元组合。

    或者当我感到懒惰时,我可以使用

    normalizer_normalize($s)===false
    

    顺便说一句:我对 ICU API 规范的这行感到困惑:

    pErrorCode 标准 ICU 错误代码。 它的输入值必须通过 U_SUCCESS() 测试,否则函数 立即返回。检查 U_FAILURE() 用于输出或与 函数链。 (请参阅用户指南了解 详细信息。)

    “函数立即返回”短语鼓励我重新执行测试,但“函数”是指 unorm2_normalize() 还是 U_SUCCESS()?有什么想法吗?

    【讨论】:

    • userguide.icu-project.org/design#TOC-Error-Handling - 基本上,如果错误代码已经是一个失败的输入,函数只会返回而不尝试做任何(更多)工作。 PHP 的包装器应该在每次调用 ICU 函数时重置错误值。这里,“函数”指的是 normalize(),而不是 U_SUCCESS()。
    猜你喜欢
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    • 2011-11-26
    • 2011-04-12
    • 2021-07-05
    • 2012-02-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多