在不升级 mysql 的情况下直接使用 mysql utf8 存储 超过三个字节的 emoji 表情

由于现在数据库的版本是5.5.2,但是看网上说要直接存储emoji表情,需要升级到5.5.3然后把字符集设置为utf8mb4,但是升级数据库感觉属于敏感操作。

考虑了多久之后直接考虑使用正则来替换,但是emoji表情的unicode码太多了,在网上找了一份代码,还是2年前更新的,想了想还是算了。

PHP 版本

最简单的办法就是直接找到接受到的文本中的字符串中4个字节的内容,做rawurlencode编码,再入库。输出的时候再替换回来,然后再用rawurldecode转码回unicode到手机再解析为emoji表情。

获取字符串长度mb_strlen,按字符来截取字符串mb_substrmb_strcut是按字节来截取,有区别)。

存储

$strEncode = ‘‘;

$length = mb_strlen($str,‘utf-8‘);

for ($i=0; $i < $length; $i++) {
    $_tmpStr = mb_substr($str,$i,1,‘utf-8‘);
    if(strlen($_tmpStr) >= 4){
        $strEncode .= ‘[[EMOJI:‘.rawurlencode($_tmpStr).‘]]‘;
    }else{
        $strEncode .= $_tmpStr;
    }
}

echo $strEncode."\n";// 周梦康123~[[EMOJI:%F0%9F%98%81]][[EMOJI:%F0%9F%98%84]]

读取

//转码回去
$strDecode = preg_replace_callback("/\[\[EMOJI:(.*?)\]\]/", function($matches){
    return rawurldecode($matches[1]);
}, $strEncode);

echo $strDecode."\n";

php 就这么轻松愉快的解决了。

Java 版本

考虑到想使用php里面的套路,对原字符串逐个字符获取其长度,如果超过3个字节,那么则编码下,就能存储了,依照上次的经验,我写了如下代码

String a = "\uD83D\uDE01";// 一个 emoji 表情
byte[] bytes = a.getBytes("utf-8");
System.out.println(bytes.length);// 输出 4

单个单个的来,能获取到正确的字节数,但是如何保证切割字符串的时候是正确的呢?我找遍了城市所有的街道,都没有,找到我要的方法.

import java.net.URLEncoder;
import java.net.URLDecoder;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.io.UnsupportedEncodingException;

public class test{

    public static void main(String[] args) throws Exception {
        String content = args[0];
        System.out.println(content);

        int strLength = content.length();

        String filterContent = emojiFilter(content);
        System.out.println(filterContent);

        String emojiStr = emojiRecovery(filterContent);
        System.out.println(emojiStr);
    }

    private static String emojiFilter(String str){
        String patternString = "([\\x{10000}-\\x{10ffff}\ud800-\udfff])";

        Pattern pattern = Pattern.compile(patternString);
        Matcher matcher = pattern.matcher(str);

        StringBuffer sb = new StringBuffer();
        while(matcher.find()) {
            try {
                matcher.appendReplacement(sb, "[[EMOJI:" + URLEncoder.encode(matcher.group(1),"UTF-8") + "]]");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
        matcher.appendTail(sb);

        return sb.toString();
    }

    private static String emojiRecovery(String str){
        String patternString = "\\[\\[EMOJI:(.*?)\\]\\]";

        Pattern pattern = Pattern.compile(patternString);
        Matcher matcher = pattern.matcher(str);

        StringBuffer sb = new StringBuffer();
        while(matcher.find()) {
            try {
                matcher.appendReplacement(sb, URLDecoder.decode(matcher.group(1),"UTF-8"));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
        matcher.appendTail(sb);

        return sb.toString();
    }
}

原文地址:https://www.cnblogs.com/exmyth/p/8378838.html

时间: 2024-10-30 09:03:33

在不升级 mysql 的情况下直接使用 mysql utf8 存储 超过三个字节的 emoji 表情的相关文章

mysql什么情况下会触发表锁

锁是计算机协调多个进程或线程并发访问某一资源的机制.在数据库中,除传统的计算资源(如CPU.RAM.I/O等)的争用以外,数据也是一种供许多用户共享的资源.如何保证数据并发访问的一致性.有效性是所有数据库必须解决的一个问题,锁冲突也是影响数据库并发访问性能的一个重要因素.从这个角度来说,锁对数据库而言显得尤其重要,也更加复杂.本章我们着重讨论MySQL锁机制的特点,常见的锁问题,以及解决MySQL锁问题的一些方法或建议. MySQL锁概述 相对其他数据库而言,MySQL的锁机制比较简单,其最显著

在不重启MySQL的情况下用gdb工具设置变量

前提:此方法只是参考其它博客的一个记录,未经亲自验证 当在mysql客户端设置一些变量时提示如下报错: 于是想能否有办法在不重启的情况下设置这些只读变量,在网上搜索别人的博客后发现如下方法 1.命令行模式下 gdb -p $(pidof mysqld) -ex "set log_error=/path/to/XXX" -batch 2.mysql客户端模式下 system gdb -p $(pidof mysqld) -ex "set log_error=/path/to/X

linux在非root权限无外网(只有内网的生产环境)情况下安装nginx+mysql+php

虽然说是非root权限,但是编译php所需要的依赖包还是需要root权限的. 安装之前先保证linux有gcc和g++,因为很多东西都需要这两个库,如果没有,运行以下命令 yum install -y gcc gcc-c++ 一般linux里面都会有,如果已经存在,它会报已经存在无法安装 一.安装nginx 1. 安装nginx前,我们需要安装3个依赖包zlib.pcre.openssl(此需要root权限) yum install -y zlib pcre openssl 2. 如果上面没有无

不停MySQL服务情况下增加从库两种常用方式

现在生产环境MySQL数据库是一主一从,由于业务量访问不断增大,故再增加一台从库.前提是不能影响线上业务使用,也就是说不能重启MySQL服务,为了避免出现其他情况,选择在网站访问量低峰期时间段操作. 一般在线增加从库有两种方式,一种是通过mysqldump备份主库,恢复到从库,mysqldump是逻辑备份,数据量大时,备份速度会很慢,锁表的时间也会很长.另一种是通过xtrabackup工具备份主库,恢复到从库,xtrabackup是物理备份,备份速度快,不锁表.为什么不锁表?因为自身会监控主库日

【MySql】linux下,设置mysql表名忽略大小写

[障碍再现] 状况描述01: 在LINUX下调一个程序经常报出找不到表,但是我明明是建了表的, 测试的时候,遇到一些问题,从Windows平台访问虚拟机中的Web应用,经常报出找不到表,但自己明明在数据库中看到相关的数据表和数据,在linux中通过MYSQL的命令行下也可以查到,为什么从Windows平台上的程序来访问虚拟机中的MySql时,就找不到呢? [原因分析] 原来是LINUX下的MYSQL默认是要区分表名大小写的,而在windows下是不区分. 从windows下导出的数据脚本中数据表

【MySql】Linux下更改转移mysql数据库目录

1.关闭MySql: #service mysqld stop 2.转移数据: #cd /var/lib   #ls   #cp -a mysql /opt/mysql/ 3.修改配置文件,一下三个: #vi /etc/my.cnf   在[client]下添加   socket=/opt/mysql/mysql.sock   注释掉之前的代码   #datadir=/var/lib/mysql   #socket=/var/lib/mysql/mysql.sock   修改为:   datad

多种字符集并存情况下sqoop从MySQL导入HBase中文乱码解决

最近在做binlog日志采集同步到数据平台的事.刚开始需要借助sqoop将从库数据表数据初始化到hbase中,整个过程都需要自动化进行,尽量减少人为干预.但是,由于历史原因,线上存在两种字符集格式的数据库(表),而导入到hbase的数据我们需要统一采用utf-8格式存储.sqoop直接导入的话,没法控制中文字符转码工作.所以需要对sqoop源码进行简单改动支持这种方式. 大体思路是,通过定义一个接口可以从InformationSchema库的tables中获取某个表的table-collatio

mysql 支持emoji表情

在mysql插入emoji表情,出现错误: java.sql.SQLException: Incorrect string value: '\xF0\x9F\x98\x8A' for column 'content' at row 原因是当前mysql的字符集为utf-8,最多3个字节,emoji表情需要4个字节来表示.所以导致insert报错. 一般的方法是将字符集改为utf8mb4 2. utf8mb4这样的字符集需要mysql 5.5才支持,当时我的版本微5.1,所以自己去官网下了5.6的

MySQL数据丢失情况分析

一.存储引擎层面丢失数据                                                       由于在实际项目中,我们往往使用支持事务的InnoDB存储引擎,MySQL默认情况下是开启内部的XA事务.我们分析InnoDB存储引擎: 从上篇的文章<MySQL事务提交过程(一)>和<MySQL事务提交过程(二)>中知道,事务的实现方式是基于redo log和undo log.也可以理解为MySQL事务是采用日志现行的策略.前提未开启binlog的情