确保有效的UTF-8 PHP(Ensuring valid utf-8 in PHP)

2019-07-21 01:06发布

我使用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;
    }
}

Answer 1:

UTF-8可以存储任何Unicode字符。 如果你的编码是别的可言,包括ISO-8859-1或Windows 1252,UTF-8的每一个字符存储在里面。 所以,你不必担心,当您从任何其他编码字符串转换为UTF-8失去任何字符。

此外,两个ISO-8859-1和Windows 1252是单字节编码,其中任何一个字节是有效的。 这在技术上是不可能来区分它们。 我会选择Windows的1252作为非UTF-8序列默认的匹配,为不同的解码唯一字节0x80-0x9F范围。 这些解码各种字符,如在ISO 8859的智能引号和欧元在Windows 1252,而它们是几乎从来没有使用隐形控制字符。 Web浏览器有时会说,他们使用的是ISO-8859-1,但他们往往真的会使用Windows 1252。

将这段代码确保字符串是安全的插入到UTF-8编码的文件

你肯定会想设置可选的“严格”参数设置为TRUE此目的。 但我不知道这实际上涵盖了所有无效的UTF-8序列。 该功能不要求显式检查UTF-8有效性的字节序列。 目前已经知道的情况下mb_detect_encoding会前猜错UTF-8,虽然我不知道这是否仍然可以在严格模式下发生的。

如果你想确保,使用自己做W3推荐的正则表达式 :

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);


Answer 2:

随着MBSTRING库,你可以mb_check_encoding() 。

使用示例:

mb_check_encoding($string, 'UTF-8');

当性能问题, 这是比接受的答案提供的正则表达式更快。

在我的配置显示了一个快速测试(20000次迭代):

  • 正则表达式:〜310ms
  • mb_check_encoding:90毫秒〜

编辑

随着PHP 7.1.9一个新的Windows 10系统上, 正则表达式的解决方案优于mb_check_encoding()对于任何字符串的长度(还是20000迭代):

  • 10个字符:正则表达式=> 4ms的, mb_check_encoding() => 64ms的
  • 10000个字符:正则表达式=> 125ms的, mb_check_encoding() => 2.4S


Answer 3:

刚一说明:除了使用通常推荐(相当复杂)的由W3C正则表达式 ,你可以简单地使用“U”修饰符来测试UTF-8有效性的字符串:

<?php
  if (preg_match("//u", $string)) {
      // $string is valid UTF-8
  }


Answer 4:

看看http://www.phpwact.org/php/i18n/charsets了约字符集指南。 这个页面链接到一个页面专门为UTF8。



Answer 5:

回答“是的iconv幂等”

也不是的iconv - 的iconv不幂等

函数utf8_encode()的iconv()之间的最大区别在于,可能的iconv提高这样的错误“检测到输入字符串不完整的多字节字符”即使有

的iconv( 'ISO-8859-1', 'UTF-8'。 '//忽略',$ STR)

在上面的代码:

$编码= mb_detect_encoding($字符串 “UTF-8,ISO-8859-1,WINDOWS-1252”);

你必须知道mb_detect_encoding可以回答UFT-8甚至是无效的UTF8字符串(格式错误的UTF8)



Answer 6:

不知道这是否会达到同样的事情,但不能你只需要使用utf8_encode()上的所有文本,而不用担心检测? 如果文本已经是UTF-8,它不会伤害它。 如果它不是,它将会被转换。 如果您已经想过这样做,是有一个原因,这不会为你工作?



文章来源: Ensuring valid utf-8 in PHP