在PHP中,我们可以使用mb_check_encoding() https://www.php.net/mb_check_encoding确定字符串是否为有效的 UTF-8。但这不是一个可移植的解决方案,因为它需要编译并启用 mbstring 扩展。此外,它不会告诉我们which字符无效。
是否有正则表达式(或其他 100% 可移植方法)可以匹配给定字符串中的无效 UTF-8 字节?
这样,如果需要,可以替换这些字节(保留二进制信息,例如在构建包含二进制数据的测试输出 XML 文件时)。因此将字符转换为 UTF-8 会丢失信息。因此,我们可能想要转换:
"foo" . chr(128) . chr(255)
Into
"foo<128><255>"
因此,只是“检测”字符串不够好,我们需要能够检测哪些字符无效。
您可以使用此 PCRE 正则表达式来检查字符串中是否存在无效 UTF-8 的字节序列。如果正则表达式匹配,则字符串包含无效的字节序列。它是 100% 可移植的,因为它不依赖 PCRE_UTF8 进行编译。
$regex = '/(
[\xC0-\xC1] # Invalid UTF-8 Bytes
| [\xF5-\xFF] # Invalid UTF-8 Bytes
| \xE0[\x80-\x9F] # Overlong encoding of prior code point
| \xF0[\x80-\x8F] # Overlong encoding of prior code point
| [\xC2-\xDF](?![\x80-\xBF]) # Invalid UTF-8 Sequence Start
| [\xE0-\xEF](?![\x80-\xBF]{2}) # Invalid UTF-8 Sequence Start
| [\xF0-\xF4](?![\x80-\xBF]{3}) # Invalid UTF-8 Sequence Start
| (?<=[\x00-\x7F\xF5-\xFF])[\x80-\xBF] # Invalid UTF-8 Sequence Middle
| (?<![\xC2-\xDF]|[\xE0-\xEF]|[\xE0-\xEF][\x80-\xBF]|[\xF0-\xF4]|[\xF0-\xF4][\x80-\xBF]|[\xF0-\xF4][\x80-\xBF]{2})[\x80-\xBF] # Overlong Sequence
| (?<=[\xE0-\xEF])[\x80-\xBF](?![\x80-\xBF]) # Short 3 byte sequence
| (?<=[\xF0-\xF4])[\x80-\xBF](?![\x80-\xBF]{2}) # Short 4 byte sequence
| (?<=[\xF0-\xF4][\x80-\xBF])[\x80-\xBF](?![\x80-\xBF]) # Short 4 byte sequence (2)
)/x';
我们可以通过创建一些文本变体来测试它:
// Overlong encoding of code point 0
$text = chr(0xC0) . chr(0x80);
var_dump(preg_match($regex, $text)); // int(1)
// Overlong encoding of 5 byte encoding
$text = chr(0xF8) . chr(0x80) . chr(0x80) . chr(0x80) . chr(0x80);
var_dump(preg_match($regex, $text)); // int(1)
// Overlong encoding of 6 byte encoding
$text = chr(0xFC) . chr(0x80) . chr(0x80) . chr(0x80) . chr(0x80) . chr(0x80);
var_dump(preg_match($regex, $text)); // int(1)
// High code-point without trailing characters
$text = chr(0xD0) . chr(0x01);
var_dump(preg_match($regex, $text)); // int(1)
etc...
事实上,由于这与无效字节匹配,因此您可以在 preg_replace 中使用它来替换它们:
preg_replace($regex, '', $text); // Remove all invalid UTF-8 code-points
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)