正在删除无效/不完整的多字节字符


Removing invalid/incomplete multibyte characters

在用户输入时使用以下代码时遇到一些问题:

htmlentities($string, ENT_COMPAT, 'UTF-8');

当检测到无效的多字节字符时,PHP抛出一个通知:

PHP警告:htmlenties():第123行/path/to/file.PHP中参数中的多字节序列无效

我的第一个想法是纠正错误,但这是一个缓慢而糟糕的练习:http://derickrethans.nl/five-reasons-why-the-shutop-operator-should-be-avoided.html

我的第二个想法是使用ENT_IGNORE标志,但即使是PHP手册也建议不要使用这个:

静默地丢弃无效的代码单元序列,而不是返回空字符串。不鼓励使用此标志,因为它可能会带来安全隐患。

还有一点原因让我想到了以下代码:

    // detect encoding
$encoding =  mb_detect_encoding($query);
if($encoding != 'UTF-8') {
    $query = mb_convert_encoding($query, 'UTF-8', $encoding);
} else {
    // strip out invalid utf8 sequences
    $query = iconv('UTF-8', 'UTF-8//IGNORE', $query);
}

不幸的是,iconv在删除/忽略无效字符时也会抛出E_NOTICE:

如果将字符串//TRANSLIT附加到out_charset,则会激活音译。这意味着,当一个字符不能在目标字符集中表示时,可以通过一个或多个外观相似的字符来近似它。如果附加字符串//IGNORE,则无法在目标字符集中表示的字符将被静默丢弃。否则,将从第一个非法字符中剪切str,并生成E_NOTICE。

所以我基本上没有选择了。我宁愿使用一个经过测试的库来处理这类事情,也不愿尝试使用我所看到的一些基于正则表达式的解决方案。

这就引出了我的最后一个问题:如何在没有通知/警告/错误的情况下高效、安全地删除无效的多字节字符

iconv('UTF-8', "ISO-8859-1//IGNORE", $string);

对我来说效果非常好。似乎没有引起任何注意。

如何在没有通知/警告/错误的情况下高效、安全地删除无效的多字节字符?

好吧,正如你在自己的问题中已经概述的那样(或者至少是链接的),删除无效的字节序列不是一个选项。

相反,它应该被替换为替换字符U+FFFD。从PHP 5.4.0开始,您可以使用htmlentitiesENT_SUBSTITUTE标志。如果你不想拒绝字符串,这可能是最安全的。

在最新的PHP版本中,如果iconv甚至没有删除整个字符串,它总是会向您发出警告。因此,这对你来说似乎不是一个好的选择。