【发布时间】:2011-07-17 11:36:23
【问题描述】:
iconv 函数有时会报错:
Notice:
iconv() [function.iconv]:
Detected an incomplete multibyte character in input string in [...]
有没有办法在将数据发送到 inconv() 之前检测 UTF-8 字符串中是否存在非法字符?
【问题讨论】:
iconv 函数有时会报错:
Notice:
iconv() [function.iconv]:
Detected an incomplete multibyte character in input string in [...]
有没有办法在将数据发送到 inconv() 之前检测 UTF-8 字符串中是否存在非法字符?
【问题讨论】:
首先,请注意无法检测文本是否属于特定的不需要的编码。您只能检查字符串在给定编码中是否有效。
您可以使用自 PHP 4.3.5 起在 preg_match [PHP Manual] 中提供的 UTF-8 有效性检查。如果给出无效字符串,它将返回0(没有附加信息):
$isUTF8 = preg_match('//u', $string);
另一种可能是mb_check_encoding [PHP Manual]:
$validUTF8 = mb_check_encoding($string, 'UTF-8');
您可以使用的另一个函数是mb_detect_encoding [PHP Manual]:
$validUTF8 = ! (false === mb_detect_encoding($string, 'UTF-8', true));
将strict 参数设置为true 很重要。
此外,iconv [PHP Manual] 允许您动态更改/删除无效序列。 (但是,如果iconv 遇到这样的序列,它会生成通知;这种行为无法更改。)
echo 'TRANSLIT : ', iconv("UTF-8", "ISO-8859-1//TRANSLIT", $string), PHP_EOL;
echo 'IGNORE : ', iconv("UTF-8", "ISO-8859-1//IGNORE", $string), PHP_EOL;
您可以使用@ 并检查返回字符串的长度:
strlen($string) === strlen(@iconv('UTF-8', 'UTF-8//IGNORE', $string));
也可以查看iconv 手册页上的示例。
【讨论】:
preg_match('!.!u', $str) 可以解决问题 - 在尝试查找任何内容之前,它会默默地检查 str 是否为 utf-8。 - 甚至不需要正则表达式中的那个点
preg_match 方法也能在空字符串上正常工作。
preg_match() 似乎是最快的(在 PHP 7 下),无论是有效/无效字符串还是短/长字符串。
您可以尝试使用mb_detect_encoding 来检测您是否有不同的字符集(与UTF-8 不同),然后在需要时使用mb_convert_encoding 转换为UTF-8。人们更有可能给你提供不同字符集的有效内容,而不是给你无效的 UTF-8。
【讨论】:
关于哪些字符在 UTF-8 中无效的规范非常明确。您可能想在尝试解析之前将其剥离。他们不应该在那里,所以如果你能在生成 XML 之前避免它,那就更好了。
参考这里:
http://www.w3.org/TR/xml/#charsets
这不是一个完整的列表。许多解析器也不允许一些低编号的控制字符,但我现在找不到完整的列表。
不过,iconv 可能对此有内置支持:
【讨论】:
在 iconv() 前面放一个@ 以抑制 NOTICE 并在源编码 id 中的 UTF-8 之后放一个 //IGNORE 以忽略无效字符:
@iconv('UTF-8//IGNORE', $destinationEncoding, $yourString);
【讨论】:
preg_match() 解决方案非常有趣,我会同意的。