【问题标题】:UTF8 Encoding IssueUTF8 编码问题
【发布时间】:2021-03-20 15:10:59
【问题描述】:

我有以下代码:

    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 时,它​​会在输出中显示为 ?

不确定我可以去哪里解决这个问题,因为 unicode 经常出现在结尾字符串中。

谢谢大家。

【问题讨论】:

    标签: php utf-8 character-encoding


    【解决方案1】:

    utf8_encodeutf8_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中不存在的好看的emoji都已经变成了?s,再也没有办法找回来了。


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

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

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

    【讨论】:

    • 感谢您的解释,这给了我:�您好�嗨❤️跨度>
    • 嘿 @IMSoP 我目前只使用一个普通的 php 变量,$string = '§5Hello §9Hi ❤️';
    • @CharlieJ 我现在看到了问题。请看我答案的新下半部分。
    猜你喜欢
    • 2013-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-14
    • 1970-01-01
    • 1970-01-01
    • 2012-02-21
    相关资源
    最近更新 更多