【问题标题】:Flawed characters when encoding Russian letters编码俄语字母时的有缺陷的字符
【发布时间】:2012-08-02 16:33:53
【问题描述】:

我正在向服务器查询一些信息(以 JSON 形式返回),尤其是名称列表,其中一个名称返回包含奇怪的字符:

Ðемања МатеÑ~ић

应该是这样的:

Немања Матејић

我尝试了以下方法:

  • 从字符串中删除 BOM(字节顺序标记)(否则 PHP 不会解码 JSON),然后使用 json_decode 对其进行解码,并直接获取名称并将其插入到我的 UTF8 编码的 MySQL 数据库中。
  • 使用带有 UTF8 排序规则的字段。

...无济于事 - 数据库中的值仍然存在缺陷。

如何解决?

编辑:

运行SHOW VARIABLES LIKE '%character%' 返回

character_set_client    utf8
character_set_connection    utf8
character_set_database  utf8
character_set_filesystem    binary
character_set_results   utf8
character_set_server    latin1
character_set_system    utf8
character_sets_dir  /data/mysql/fuentez/share/mysql/charsets/

可能是因为 character_set_server 是 latin1 吗?

【问题讨论】:

标签: encoding utf-8 json


【解决方案1】:

这可能是一种方便的使用俄罗斯符号的 json 格式:

新的 json_decode 函数

    <?php
    function json_encode_my($value) 
    {
        if (is_int($value)) {
            return (string)$value;   
        } elseif (is_string($value)) {
            $value = str_replace(array('\\', '/', '"', "\r", "\n", "\b", "\f", "\t"), 
                                 array('\\\\', '\/', '\"', '\r', '\n', '\b', '\f', '\t'), $value);
            $convmap = array(0x80, 0xFFFF, 0, 0xFFFF);
            $result = "";
            for ($i = mb_strlen($value) - 1; $i >= 0; $i--) {
                $mb_char = mb_substr($value, $i, 1);
                if (mb_ereg("&#(\\d+);", mb_encode_numericentity($mb_char, $convmap, "UTF-8"), $match)) {
                    $result = sprintf("\\u%04x", $match[1]) . $result;
                } else {
                    $result = $mb_char . $result;
                }
            }
            return '"' . $result . '"';                
        } elseif (is_float($value)) {
            return str_replace(",", ".", $value);         
        } elseif (is_null($value)) {
            return 'null';
        } elseif (is_bool($value)) {
            return $value ? 'true' : 'false';
        } elseif (is_array($value)) {
            $with_keys = false;
            $n = count($value);
            for ($i = 0, reset($value); $i < $n; $i++, next($value)) {
                        if (key($value) !== $i) {
                  $with_keys = true;
                  break;
                        }
            }
        } elseif (is_object($value)) {
            $with_keys = true;
        } else {
            return '';
        }
        $result = array();
        if ($with_keys) {
            foreach ($value as $key => $v) {
                $result[] = json_encode((string)$key) . ':' . json_encode($v);    
            }
            return '{' . implode(',', $result) . '}';                
        } else {
            foreach ($value as $key => $v) {
                $result[] = json_encode($v);    
            }
            return '[' . implode(',', $result) . ']';
        }

}
?>

【讨论】:

    【解决方案2】:

    您将数据库中的数据存储为 latin1 而不是 UTF-8。

    例如,编码为 latin1 的字符串 е 变为 0xd0 0xb5,这是西里尔字母 е 的 UTF-8 编码。

    【讨论】:

    • 插入时需要将连接上的编码设置为UTF-8。您使用的是什么数据库库?你能发布你的插入代码吗?
    • @SteffanLong:也许这对你有帮助? stackoverflow.com/questions/4475548/…
    • 谢谢,将它添加到我的 PDO 初始化中就可以了!
    猜你喜欢
    • 2013-12-08
    • 1970-01-01
    • 1970-01-01
    • 2011-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-15
    • 2016-12-27
    相关资源
    最近更新 更多