首页 > 解决方案 > UTF8 编码问题

问题描述

我有以下代码:

    function parseMinecraftColors($string) {
        $string = utf8_decode(htmlspecialchars($string, ENT_QUOTES, "UTF-8"));
        $string = preg_replace('/\xA7([0-9a-f])/i', '<span class="mc-color mc-$1">', $string, -1, $count) . str_repeat("</span>", $count);
        return utf8_encode(preg_replace('/\xA7([k-or])/i', '<span class="mc-$1">', $string, -1, $count) . str_repeat("</span>", $count));
    }

它将一个字符串翻译成Hi §5Person它的 HTML 表单(带有基于颜色的类)。但是,当使用诸如❤️或任何其他的 unicode 时,它​​会?在输出中显示。

不知道我可以去哪里解决这个问题,因为 unicodes 通常出现在结尾字符串中。

谢谢大家。

标签: phputf-8character-encoding

解决方案


utf8_encode并且utf8_decode是命名错误的函数,它们很少是你想要的。

让我们看看您正在使用的编码:

htmlspecialchars($string, ENT_QUOTES, "UTF-8")

在这里,您告诉htmlspecialchars您的字符串被编码为 UTF-8。到目前为止,一切都很好。

$string = utf8_decode(...);

现在,您告诉utf8_decode将字符串从 UTF-8 转换为 ISO-8859-1 编码。ISO-8859-1 是单字节编码,只能表示 256 个不同的字符,当然不包含任何表情符号。如手册所述:

字符串中不是有效 UTF-8 的字节,以及 ISO-8859-1 中不存在的 UTF-8 字符(即 U+00FF 以上的字符)被替换为 ?。

执行其余代码后,然后运行:

return utf8_encode(...)

这告诉utf8_encode将您的 ISO-8859-1 字符串转换回 UTF-8。但是已经太晚了,那些在ISO-8859-1中不存在的漂亮表情都已经变成了?s,没有办法找回它们。


如果你去掉 utf8_decode 和 utf8_encode 调用,你会遇到不同的问题:PCRE 正则表达式函数(例如 preg_replace)默认只对单个字节起作用,但在 UTF-8§中是两个字节长。因此,当您替换 byte 时A7,您将替换“半个字符”,留下一个无效的字符串。

您可以通过以下两种方式之一解决此问题:

  • 将正则表达式保留为单字节模式,但匹配正确的字节序列,即C2 A7; 例如preg_replace('/\xC2\xA7([0-9a-f])/i', ...
  • 通过添加修饰符u正则表达式置于 UTF8 模式,并引用 Unicode 代码点§A7; 例如preg_replace('/\xA7([0-9a-f])/iu', ...

简而言之,试试这个:

function parseMinecraftColors($string) {
    $string = htmlspecialchars($string, ENT_QUOTES, "UTF-8");
    $string = preg_replace('/\xC2\xA7([0-9a-f])/i', '<span class="mc-color mc-$1">', $string, -1, $count) . str_repeat("</span>", $count);
    return preg_replace('/\xC2\xA7([k-or])/i', '<span class="mc-$1">', $string, -1, $count) . str_repeat("</span>", $count);
}

或这个:

function parseMinecraftColors($string) {
    $string = htmlspecialchars($string, ENT_QUOTES, "UTF-8");
    $string = preg_replace('/\xA7([0-9a-f])/iu', '<span class="mc-color mc-$1">', $string, -1, $count) . str_repeat("</span>", $count);
    return preg_replace('/\xA7([k-or])/iu', '<span class="mc-$1">', $string, -1, $count) . str_repeat("</span>", $count);
}

推荐阅读