我正在使用PHP来处理来自各种来源的文本。我不认为它将是UTF-8,ISO-8859-1或WINDOWS-1252以外的任何东西。如果它不是其中之一,我只需要确保文本变成有效的UTF-8字符串,即使字符丢失也是如此。 iconv的// TRANSLIT选项是否解决了这个问题?例如,此代码是否确保字符串可以安全地插入到UTF-8编码的文档(或数据库)中?
function make_safe_for_utf8_use($string) {
$encoding = mb_detect_encoding($string, "UTF-8,ISO-8859-1,WINDOWS-1252");
if ($encoding != 'UTF-8') {
return iconv($encoding, 'UTF-8//TRANSLIT', $string);
} else {
return $string;
}
}
答案 0 :(得分:37)
UTF-8可以存储任何Unicode字符。如果你的编码是其他任何东西,包括ISO-8859-1或Windows-1252,UTF-8可以存储其中的每个字符。因此,当您将字符串从任何其他编码转换为UTF-8时,您不必担心会丢失任何字符。
此外,ISO-8859-1和Windows-1252都是单字节编码,其中任何字节都有效。从技术上讲,区分它们是不可能的。我会选择Windows-1252作为非UTF-8序列的默认匹配,因为唯一不同的解码字节是0x80-0x9F。这些解码到各种字符,如智能引号和Windows-1252中的欧元,而在ISO-8859-1中,它们是几乎从不使用的隐形控制字符。 Web浏览器有时可能会说他们正在使用ISO-8859-1,但他们通常会使用Windows-1252。
此代码是否确保字符串可以安全地插入到UTF-8编码的文档中
为此,您肯定希望将可选的'strict'参数设置为TRUE。但我不确定这实际上涵盖了所有无效的UTF-8序列。该函数并未声明明确检查字节序列的UTF-8有效性。有一些已知的情况,mb_detect_encoding之前会错误地猜测UTF-8,但我不知道是否仍然可以在严格模式下发生。
如果您想确定,请使用W3-recommended regex:
自行完成if (preg_match('%^(?:
[\x09\x0A\x0D\x20-\x7E] # ASCII
| [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
| \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
| [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte
| \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates
| \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
| [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15
| \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
)*$%xs', $string))
return $string;
else
return iconv('CP1252', 'UTF-8', $string);
答案 1 :(得分:14)
使用 mbstring 库,您有 mb_check_encoding() 。
使用示例:
mb_check_encoding($string, 'UTF-8');
当表现很重要时,这比接受的答案中提供的正则表达式更快。</ strike>
我的配置快速测试显示(20,000次迭代):
击>修改强>
在最新的Windows 10系统上使用PHP 7.1.9时,正则表达式解决方案的性能优于mb_check_encoding()
任何字符串长度(仍然是20,000次迭代):
mb_check_encoding()
=&gt; 64ms的mb_check_encoding()
=&gt; 2.4S 答案 2 :(得分:3)
只需注意:您可以使用“u”修饰符来测试字符串的UTF-8有效性,而不是使用经常推荐的(相当复杂的)regular expression by W3C:
<?php
if (preg_match("//u", $string)) {
// $string is valid UTF-8
}
答案 3 :(得分:1)
请查看 http://www.phpwact.org/php/i18n/charsets以获取有关字符集的指南。此页面链接到专门针对utf8的页面。
答案 4 :(得分:0)
回答“iconv是幂等的”
也不是iconv - iconv不是幂等的
utf8_encode()与...之间的巨大差异的iconv() 是iconv可能会引发错误,如“在输入字符串中检测到不完整的多字节字符” 即使用
iconv('ISO-8859-1','UTF-8'。'// IGNORE',$ str)
在上面的代码中:
$ encoding = mb_detect_encoding($ string,“UTF-8,ISO-8859-1,WINDOWS-1252”);
你必须知道mb_detect_encoding即使对于无效的utf-8字符串(形成错误的utf8)也可以回答uft-8
答案 5 :(得分:-1)
不确定这是否可以达到同样的效果,但是你不能在所有文本上使用utf8_encode()
而不用担心检测吗?如果文本已经是UTF-8,那么它不会受到伤害。如果不是,它将被转换。如果你已经考虑过这样做,那么这对你不起作用吗?