从字符串中删除非 utf8 字符
我在从字符串中删除非utf8字符时遇到问题,这些字符无法正确显示。字符0x97 0x61 0x6C 0x6F(十六进制表示形式)中如下所示
删除它们的最佳方法是什么?正则表达式还是其他东西?
我在从字符串中删除非utf8字符时遇到问题,这些字符无法正确显示。字符0x97 0x61 0x6C 0x6F(十六进制表示形式)中如下所示
删除它们的最佳方法是什么?正则表达式还是其他东西?
如果应用于已存在的 UTF8 字符串,它将返回乱码 UTF8 输出。utf8_encode()
我制作了一个解决所有这些问题的函数。它被称为.Encoding::toUTF8()
您不需要知道字符串的编码是什么。它可以是 Latin1 (ISO8859-1)、Windows-1252 或 UTF8,或者字符串可以混合使用它们。 会将所有内容转换为 UTF8。Encoding::toUTF8()
我这样做是因为一个服务给我一个数据馈送,所有数据都搞砸了,将这些编码混合在同一个字符串中。
用法:
require_once('Encoding.php');
use \ForceUTF8\Encoding; // It's namespaced now.
$utf8_string = Encoding::toUTF8($mixed_string);
$latin1_string = Encoding::toLatin1($mixed_string);
我包含了另一个函数,Encoding::fixUTF8(),它将修复每个看起来乱码的UTF8字符串,这些字符串已被多次编码为UTF8。
用法:
require_once('Encoding.php');
use \ForceUTF8\Encoding; // It's namespaced now.
$utf8_string = Encoding::fixUTF8($garbled_utf8_string);
例子:
echo Encoding::fixUTF8("Fédération Camerounaise de Football");
echo Encoding::fixUTF8("Fédération Camerounaise de Football");
echo Encoding::fixUTF8("FÃÂédÃÂération Camerounaise de Football");
echo Encoding::fixUTF8("Fédération Camerounaise de Football");
将输出:
Fédération Camerounaise de Football
Fédération Camerounaise de Football
Fédération Camerounaise de Football
Fédération Camerounaise de Football
下载:
使用正则表达式方法:
$regex = <<<'END'
/
(
(?: [\x00-\x7F] # single-byte sequences 0xxxxxxx
| [\xC0-\xDF][\x80-\xBF] # double-byte sequences 110xxxxx 10xxxxxx
| [\xE0-\xEF][\x80-\xBF]{2} # triple-byte sequences 1110xxxx 10xxxxxx * 2
| [\xF0-\xF7][\x80-\xBF]{3} # quadruple-byte sequence 11110xxx 10xxxxxx * 3
){1,100} # ...one or more times
)
| . # anything else
/x
END;
preg_replace($regex, '$1', $text);
它搜索 UTF-8 序列,并将其捕获到组 1 中。它还匹配无法识别为 UTF-8 序列一部分的单个字节,但不捕获这些字节。替换是被捕获到第1组中的任何内容。这有效地删除了所有无效字节。
通过将无效字节编码为 UTF-8 字符,可以修复字符串。但是,如果错误是随机的,这可能会留下一些奇怪的符号。
$regex = <<<'END'
/
(
(?: [\x00-\x7F] # single-byte sequences 0xxxxxxx
| [\xC0-\xDF][\x80-\xBF] # double-byte sequences 110xxxxx 10xxxxxx
| [\xE0-\xEF][\x80-\xBF]{2} # triple-byte sequences 1110xxxx 10xxxxxx * 2
| [\xF0-\xF7][\x80-\xBF]{3} # quadruple-byte sequence 11110xxx 10xxxxxx * 3
){1,100} # ...one or more times
)
| ( [\x80-\xBF] ) # invalid byte in range 10000000 - 10111111
| ( [\xC0-\xFF] ) # invalid byte in range 11000000 - 11111111
/x
END;
function utf8replacer($captures) {
if ($captures[1] != "") {
// Valid byte sequence. Return unmodified.
return $captures[1];
}
elseif ($captures[2] != "") {
// Invalid byte of the form 10xxxxxx.
// Encode as 11000010 10xxxxxx.
return "\xC2".$captures[2];
}
else {
// Invalid byte of the form 11xxxxxx.
// Encode as 11000011 10xxxxxx.
return "\xC3".chr(ord($captures[3])-64);
}
}
preg_replace_callback($regex, "utf8replacer", $text);
编辑:
!empty(x)
将匹配非空值(被视为空)。"0"
x != ""
将匹配非空值,包括 ."0"
x !== ""
将匹配除 以外的任何内容。""
x != ""
在这种情况下似乎是最好的一个。
我也加快了比赛的速度。它不是单独匹配每个字符,而是匹配有效 UTF-8 字符的序列。