0

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

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

4

2 回答 2

2

自 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)
]);
于 2013-05-31T14:15:30.097 回答
0

我做了一些挖掘,发现了ICU unorm2_normalize() 文档。它的 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()?有任何想法吗?

于 2011-07-09T21:31:27.297 回答