使用PHP的 intl 包装器中当前可用的功能,您将如何检查字符串编码的有效性? (例如检查有效的UTF-8)
我知道可以使用mbstring,iconv()和PCRE完成,但我对此问题特别感兴趣。
答案 0 :(得分: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)
]);
答案 1 :(得分:0)
我做了一些挖掘并找到了ICU unorm2_normalize() documentation。它的pErrorCode输出参数很有趣。标准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
Btw:我对ICU API规范的这一行感到困惑:
pErrorCode 标准ICU错误代码。 它的输入值必须通过 U_SUCCESS ()测试,否则函数 马上回来。检查 U_FAILURE ()输出或使用 功能链。 (请参阅用户指南 的信息。)
“函数立即返回”这句话鼓励我的测试重新执行,但“函数”是指unorm2_normalize()还是U_SUCCESS()?有什么想法吗?