颖想家

所谓幸福就是你在,我在,你一直在,我一直在

mysql存储与备份Emoji的方法

Emoji 表情简单的存储到MySQL中直接报错:Incorrect string value: '\xF0\x9F\x98\x80' for column 'data' at row 1

这个错误的原因是由于字符集不支持造成的,因为 Emoji 表情占用4个字节,而 MySql的 utf8 编码最多只能存储3个字节,所以导致数据插入失败。在读取的时候读取不完整,导致乱码。

一、如何解决Emoji存储问题?

MySQL的版本不能太低,低于5.5.3的版本不支持utf8mb4编码。通过 select version(); 可以查看MySQL的版本。

1、MySQL的版本低于5.5.3

如果不愿意更换MySQL的版本,当遇到emoji字符表情的时候只能做特殊处理。网上也有很多处理方案,最后找到了一个贴上地址和代码:https://github.com/BriquzStudio/php-emoji

class Emoji

{

    /**

     * Encode emoji in text

     * @param string $text text to encode

     */

    public static function Encode($text) {

        return self::convertEmoji($text,"ENCODE");

    }

    /**

     * Decode emoji in text

     * @param string $text text to decode

     */

    public static function Decode($text) {

        return self::convertEmoji($text,"DECODE");

    }

    private static function convertEmoji($text,$op) {

        if($op=="ENCODE"){

            return preg_replace_callback('/([0-9|#][\x{20E3}])|[\x{00ae}|\x{00a9}|\x{203C}|\x{2047}|\x{2048}|\x{2049}|\x{3030}|\x{303D}|\x{2139}|\x{2122}|\x{3297}|\x{3299}][\x{FE00}-\x{FEFF}]?|[\x{2190}-\x{21FF}][\x{FE00}-\x{FEFF}]?|[\x{2300}-\x{23FF}][\x{FE00}-\x{FEFF}]?|[\x{2460}-\x{24FF}][\x{FE00}-\x{FEFF}]?|[\x{25A0}-\x{25FF}][\x{FE00}-\x{FEFF}]?|[\x{2600}-\x{27BF}][\x{FE00}-\x{FEFF}]?|[\x{2600}-\x{27BF}][\x{1F000}-\x{1FEFF}]?|[\x{2900}-\x{297F}][\x{FE00}-\x{FEFF}]?|[\x{2B00}-\x{2BF0}][\x{FE00}-\x{FEFF}]?|[\x{1F000}-\x{1F9FF}][\x{FE00}-\x{FEFF}]?|[\x{1F000}-\x{1F9FF}][\x{1F000}-\x{1FEFF}]?/u',array('self',"encodeEmoji"),$text);

        }else{

            return preg_replace_callback('/(\\\u[0-9a-f]{4})+/',array('self',"decodeEmoji"),$text);

        }

    }

    private static function encodeEmoji($match) {

        return str_replace(array('[',']','"'),'',json_encode($match));

    }

     

    private static function decodeEmoji($text) {

        if(!$text) return '';

        $text = $text[0];

        $decode = json_decode($text,true);

        if($decode) return $decode;

        $text = '["' . $text . '"]';

        $decode = json_decode($text);

        if(count($decode) == 1){

           return $decode[0];

        }

        return $text;

    }

}


上面类的使用方法

<?php

    require_once('path/to/Emoji.php');

    //encode

    $text = '😄,hi';

    echo Emoji::Encode($text);

    //decode

    $text='\ud83d\ude04,hi';

    echo Emoji::Decode($text);

?>


2、MySQL的版本大于等于5.5.3

MySQL的字符集的作用域有三个层级,分别是数据库级、表级、列级(字段级别的)。优先级是:列级 > 表级 > 数据库级。从优先级知道如果存emoji的那个字段不是utf8mb4字符集,如果不是,那么即使数据库是utf8mb4也是无济于事的。

把对应要存储emoji的字段的字段类型的字符集改为utf8mb4,排序规则改为utf8mb4_general_ci即可。

alter table admin modify user_name varchar(100) charset utf8mb4 NOT NULL DEFAULT '' COMMENT '用户名';


二、如何解决Emoji数据备份的问题?

正常情况下我们导出备份数据的方法如下:

mysqldump -h 服务器IP地址 -u 用户名 -p 密码 --opt 数据库名>备份数据库名

mysqldump -h localhost -u root -p --opt user>food2007-08-24-04.sql

这条命令将服务器localhost上的user这个数据库备份到本地计算机当前目录的user2020-04-06.sql这个文件中,这样,当数据库不小心损坏或数据丢失时,就可以由user2020-04-06.sql这个备份文件恢复了。

但对于数据中有Emoji的数据,在执行备份命令时,指定字符集即可(@see mysqldump --help)

mysqldump -utest -p123456 --default-character-set=utf8mb4 db_name > db_name_bak.sql

这样的备份数据恢复后就不会产生emoji丢失的情况。不指定字符集直接备份的话,因默认字符集是 utf8 会导致 emoji 表情无法备份到文件。

写在最后

能将MySQL升级的最好还是升级,毕竟MySQL5.7的性能还是比之前的版本强很多。

发表留言