【问题标题】:File read to DB insert resulting in unicode strings文件读取到数据库插入导致 unicode 字符串
【发布时间】:2018-03-22 04:15:43
【问题描述】:

我正在从文件中读取 JSON 字符串,对其进行解析,然后将数据插入 MySQL 数据库。我的插入查询抛出以下错误:

SQLSTATE[HY000]: General error: 1366 Incorrect string value: '\xE3\xADs' for column 'fname' at row 1

我相信导致错误的内容是名称 Ailís 中的 í(我回显了 ID,直到引发错误)。

  • 文件采用 UTF8 编码
  • 我正在使用 UTF8 上下文读取文件
  • 我正在检查数据的编码是否为 UTF8(它是)
  • 我的 PDO 连接有一个 UTF8 字符集,以及SET NAMES utf8
  • 数据库采用 UTF8 编码
  • 表格采用 UTF8 编码
  • 该列采用 UTF8 编码

代码:

$opts = ['http' => ['header' => 'Accept-Charset: UTF-8, *;q=0']];
$context = stream_context_create($opts);
$post = file_get_contents('sample_data/11111a_json_upload.json',false, $context);
if(!mb_check_encoding($post, 'UTF-8'))
    throw new Exception('Invalid encoding detected.');
$data = json_decode($post, true);

在解码 JSON 之前,我还插入了以下函数:

static function clean_unicode_literals($string)
{
    return preg_replace_callback('@\\\(x)?([0-9a-zA-Z]{2,3})@',
        function ($m) {
            if ($m[1]) {
                $hex = substr($m[2], 0, 2);
                $unhex = chr(hexdec($hex));
                if (strlen($m[2]) > 2) {
                    $unhex .= substr($m[2], 2);
                }
                return $unhex;
            } else {
                return chr(octdec($m[2]));
            }
        }, $string);
}

当我读取原始文件并将解析的数据回显到浏览器时,名称显示正确。因此,我认为问题出在我的联系中?

我像这样创建一个新的 PDO 实例:

public function __construct($db_user, $db_pass, $db_name, $db_host, $charset)
{
    if(!is_null($db_name))
        $dsn = 'mysql:host=' . $db_host . ';dbname=' . $db_name . ';charset=' . $charset;
    else
        $dsn = 'mysql:host=' . $db_host . ';charset=' . $charset;

    $options = [
        PDO::ATTR_PERSISTENT => true,
        PDO::ATTR_ERRMODE    => PDO::ERRMODE_EXCEPTION,
        PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8'"
    ];

    try
    {
        $this->db_handler = new PDO($dsn, $db_user, $db_pass, $options);
        $this->db_handler->exec('SET NAMES utf8');
        $this->db_valid = true;
    }
    catch(PDOException $e)
    {
        $this->db_error = $e->getMessage();
        $this->db_valid = false;
    }

    return $this->db_valid;
}

(在我进行故障排除时,SET NAMES 出现了两次...)
数据库、表和列字符集设置为utf8_general_ci

我的 IDE 是 PHPStorm,我在 Windows 10 上运行 WAMP MySQL 5.7.14。

【问题讨论】:

  • 那么实际插入的代码在哪里?

标签: php mysql json


【解决方案1】:

输入字符串肯定有问题:\xE3\xADs

第一个半字节E表示应该是一个3字节的UTF-8序列,但是只有两个字节。

而且绝对不是í,因为那是两字节序列\xC3\xAD

我想知道为什么你有 clean_unicode_literals 函数,因为根据 JSON 规范,所有 JSON 字符串和文档都应该是有效的 UTF-8。

尝试删除 clean_unicode_literals 调用,如果仍然出现错误,则源数据已损坏。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-24
    • 2012-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-25
    相关资源
    最近更新 更多