当前位置: 首页 > 编程日记 > 正文

Emoji表情图标在iOS与PHP之间通信及MySQL存储

在某个 iOS 项目中,需要一个服务器来保存一些用户数据,例如用户信息、评论等,我们的服务器端使用了 PHP+MySQL 的搭配。在测试过程中我们发现,用户在 iOS 端里输入了 Emoji 表情提交到服务器以后,PHP 无法在 MySQL 数据库里正确保存,会遇到乱码的问题。下面是原因探析和解决办法。

说起 Emoji 的历史说开去那可谓是源远流长了,这里简要介绍 Emoji 在 iOS 系统中的变迁史。不知道何时起,日本人喜欢发 Emoji 表情图标,于是日本的运营商 DoCoMo、KDDI、SoftBank 推出了自己的 Emoji 字符集。在这些字符集中,一个 Emoji 表情的实际上是一个 UTF8 字符,这点不同于 QQ 或者微信的表情,用户发短信的时候一个 Emoji “图像”只占用了一个字符,那是相当的方便。苹果的 iOS 和 Mac OS X 系统内置了 Apple Color Emoji(Apple 彩色表情符号)的字体用来显示 Emoji 表情,iOS 里有一个 Emoji 输入键盘,可以输入各种 Emoji 表情图标,在 Mac OS X 里使用 Option + Command + T 调出输入键盘里选择“表情符号”输入,Mac OS X 里的字体文件位于 /System/Library/Fonts/Apple Color Emoji.ttf。抛开版权因素,把这个文件拷贝到 Windows 的字库文件夹里,Windows 也能支持 Emoji 的显示了。

从技术上说,单个 Emoji 表情实际上是使用 UTF8 编码的一个字符,苹果在 iOS4 开始支持了 Emoji 的显示,当时用的是 SoftBank 的方案。在日本的三家运营商之间,用来表示同一个表情的 UTF8 码并不相同(见对比列表),他们之间要做一个转换才能正确显示。以相同一个表情笑脸为例,SoftBank 表示为 U+E04A,KDDI 则表示为 U+E488

iOS4 的解决方案

不过唯一的好处在于,这时候的每个 Emoji 图标,都是使用 3 字节的 UTF8 字符编码。说句题外话,在刚开始 PHP 开发的时候,大家都知道一个中文在 UTF8 字符集占据 3 个字节。 回到 iOS 和 Web 服务器之间的通信方案,我们可以直接把 iOS 中用户输入的 Emoji 表情,通过 PHP 存入 MySQL 数据库中,如果在 iOS 中展示,直接把数据传递给 iOS,客户端应该就能正确展示表情图标了,如果把用户在 iOS 端输入的表情在 Web 端展示,需要把 Emoji 字符转化为对应的图片(当然支持 Emoji 的 Mac OS X 系统可以通过指定网页 CSS 的 font-family 属性直接显示)。Emoji for PHP 组件能够方便地在各种 Unified、DoCoMo、KDDI、SoftBank、Google 编码之间进行转换。

iOS5 的解决方案

从 iOS5 开始,苹果开始支持标准的 Unified 编码的 Emoji 表情。这其中最大的优点莫过于统一了规格,方便了用户和开发者。但是,Web 开发者在开发网页端的时候就会遇到一些问题,以往直接把 Emoji 表情存储在数据库中现在则会导致乱码。这是由于采用 Unified 标准的单个 Emoji 字符一般为 4 个字节,超过了 MySQL 数据库 utf8 字符集支持的每个字符 3 个字节的限制,存入数据库以后会产生乱码或者破坏数据。

如果说解决该问题,最方便的做法是在存入数据库之前,把每个 Emoji 字符转化为 UBB 代码,或者是其他可辨认的形式,如 HTML 转义字符。还是以太阳符号为例,它的 Unified Emoji 编码为 U+2600,在存入数据库时,可以把它转换成  UBB 代码 [emoji]2600[/emoji] 保存,也可以使用 HTML 转义字符 ☀ 储存。如果在 Web 前端展示,用 HTML 转义字符可以直接输出,用 UBB 代码则方便论坛等需要严格安全验证用户输入的地方使用。

还有一种做法你可能也猜到了,采用 SoftBank 方案的单个 Emoji 表情占用 3 个字节,可以直接保存在数据库里,所以可以把 Unified Emoji 转化为 SoftBank Emoji 格式,存储在数据库中就不会有任何问题了。

另外一种方式从 MySQL 自身解决。从 MySQL 5.5.3 开始,MySQL 支持一种 utf8mb4 的字符集,这个字符集能够支持 4 字节的 UTF8 编码的字符。 utf8mb4 字符集能够完美地向下兼容 utf8 字符串。在数据存储方面,当一个普通中文字符存入数据库时仍然占用 3 个字节,在存入一个 Unified Emoji 表情的时候,它会自动占用 4 个字节。所以在输入输出时都不会存在乱码的问题了。要使用 MySQL 的这个特性,首先需要把 MySQL 升级到 5.5.3 以上的版本。其次,需要修改数据结构中的字符集为 utf8mb4 ,如 utf8mb4_general_ci 。由于 utf8mb4 是 utf8 的超集,从 utf8 升级到 utf8mb4 不会有任何问题,直接升级即可;如果从别的字符集如 gb2312 或者 gbk 转化而来,一定要先备份数据库。然后,修改 MySQL 的配置文件 /etc/my.cnf,修改连接默认字符集为 utf8mb4 ,如果是自己写的 PHP 脚本,也可以在连接数据库以后首先执行一句 SQL: SET NAMES utf8mb4;。这时候,PHP 应该就可以正常保存 Emoji 到数据库了。

iOS6 的解决方案

苹果在 iOS6 和 Mac OS X 10.8 中又增加了 300 多个 Emoji 表情,而 SoftBank 编码因为渐渐被历史淘汰,已经没有了相应的升级,所以上文提到的把 Unified Emoji 转化为 SoftBank Emoji 后保存在数据库中的方案已经落伍了。

最终解决方案

说了那么多,最终还是要归纳总结一下解决方法。

从数据库中保存的形态出发,要么用 UBB 或者 HTML 转义字符等替代方法保存,要么用数据库直接存储 Emoji 字符。如果直接保存 Emoji 字符,则必须将 MySQL 升级到 5.5.3 以上并且采用 utf8mb4 字符集。如果用替代方法,则不用升级数据库,不影响现有的服务器,是比较省事的方法。

在用户输入方面,以某著名门户新闻客户端为例,常见的几个平台包括:Web,iOS,安卓等。 Web 端上主要是让用户通过点击图标输入 Emoji 表情,在文本框里可以直接以 UBB 代码[emoji]2600[/emoji] 的形式显示,也要考虑 Mac OS X 或 iOS 移动网页端用户直接通过键盘输入 Emoji 字符,这时候最好在 CSS 里添加 textarea{font-family:"Apple Color Emoji","Arial";} ,以便 Mac OS X 上的 Chrome / Firefox 浏览器用户输入了表情以后能直接显示出来,而不是黑框框。iOS 客户端不必说了,直接让用户使用 iOS 自带的表情键盘即可。至于 Android, Windows Phone 或者黑莓等其他平台,一般要通过第三方的输入法来输入 Emoji 表情。至于用户输入的 Emoji 字符还是 UBB 代码,服务器端应该都要有处理的能力。值得注意的是,可能 SoftBank 等 Emoji 字符集都已经不是主流了,在中国的用户估计很少,但如果你想做一个像微信那么跨国界的 APP,还是不妨加一个转换,首先将各种形式的 Emoji 字符首先转换为 Unified Emoji。

在 Web 端显示方面,出于各平台的兼容性考虑,把 Emoji 表情通过图片输出是最合适的做法。无论在数据库中我们保存的形态是什么,把它转化为图片都需要一个对应表。Emoji for PHP已经实现了 iOS5 的 500 多个表情的支持,但尚未提供 iOS6 新增的 300 多个表情。我虽然已经做了对应关系,但是因为没有整理出代码,暂时没办法放出来。

在 iOS 端显示方面,鉴于用户普遍升级到 iOS5 以上,自然是显示原生支持的 Unified Emoji。在安卓和其他移动平台客户端上,我暂时没有研究过,但估计显示图片是比较好的选择。

参考资料:

  • http://blog.manbolo.com/2012/10/29/supporting-new-emojis-on-ios-6
  • http://opensource.apple.com/source/ICU/ICU-461.13/icuSources/data/translit/Any_SoftbankSMS.txt
  • http://punchdrunker.github.com/iOSEmoji/table_html/
  • http://code.iamcal.com/php/emoji/
  • http://www.unicode.org/Public/UNIDATA/EmojiSources.txt

相关文章:

【linux】图形界面基础知识(X、X11、GNOME、Xorg、KDE的概念和它们之间的关系)

转载自:https://blog.csdn.net/zhangxinrun/article/details/7332049 简介 LINUX初学者经常分不清楚linux和X之间,X和Xfree86之间,X和KDE,GNOME等之间是什么关系。常常混淆概念,本文以比较易于理解的方式来解释X&…

DreamWeaver做ASP 第13页

第七步:修改资料篇 修改资料!首先要清醒一点,什么人才可以修改。 一,本人只能修改自己的;二,管理员可以修改所有人的。 那今天先来搞个可以修改自己资料的页面。 顺序是:先确认是正确登录&#…

【linux命令】setterm控制终端属性命令(中英文)

###setterm中文 SETTERM(1) 用户命令 SETTERM(1) 名字 setterm - 设置终端属性 概要 setterm [选项] 描述 setterm向终端写一个字符串到标准输出,调用终端的特定功能。在虚拟终端上使用,将会改变虚拟终端的输出特性。不支持的选项将被忽略。 选项 对…

搜狗分身技术再进化,让AI合成主播“动”起来

整理 | 一一出品 | AI科技大本营去年 11 月的互联网大会期间,搜狗与新华社联合发布全球首个AI合成主播一经亮相,引起了人们对“AI媒体”的广泛讨论。如今,搜狗 AI 合成主播不断更新迭代。2 月 19 日,在新华社新媒体中心与搜狗公司…

Angular http跨域

var app angular.module(Mywind,[ui.router]); app.controller(Myautumn,function($scope,$http,$filter){ //$http跨域 //服务端设置 // 访问权限 response.setHeader("Access-Control-Allow-Origin", "*"); // 访问类型 response.setHeader(&q…

文本分类step by step(二)

(注:如有转载请标明作者:finallyliuyu, 和出处:博客园) 《文本分类 step by step(一)》 在《文本分类step by step(一)》中,我们从处理语料库开始讲起,一直讲到利用分类器…

Centos7.4 版本环境下安装Mysql5.7操作记录

Centos7.x版本下针对Mysql的安装和使用多少跟之前的Centos6之前版本有所不同的,废话就不多赘述了,下面介绍下在centos7.x环境里安装mysql5.7的几种方法:一、yum方式安装 Centos7.x版本下针对Mysql的安装和使用多少跟之前的Centos6之前版本有所…

叫你一声“孙悟空”,敢答应么?

整理 | 一一出品 | AI科技大本营(ID:rgznai100)随着自然语言理解等技术的发展,对话机器人如今盛行,而基于此的智能音箱产品的发展也异常火热。很多开发者一般热衷于在一些对话机器人平台上开发相应的语音技能,但也有不…

【linux】Matchbox(一):启动脚本

脚本执行顺序 启动X服务器 /etc/rc5.d/S01xserver-nodm --> …/init.d/xserver-nodm–> 对应进程: /bin/sh /etc/rc5.d/S01xserver-nodm start background xinit /etc/X11/Xsession–> 对应进程: xinit /etc/X11/Xsession – /usr/bin/Xorg …

java试用(1)hello world

设置环境变量path H:\soft\j2sdk1.4.2_17\bin;H:\soft\eclipse;%path%set CLASSPATH.;H:\soft\j2sdk1.4.2_17\jre\lib;JAVA_HOME: D:\jdk1.5.0PATH: D:\jdk1.5.0\bin;编写程序 Noname1.java (注意:文件名要和class名一样)class Noname1 { public static void…

GAN性能不稳?这九大技术可“镇住”四类缺陷

作者 | Bharath Raj译者 | ang010ela编辑 | 一一出品 | AI科技大本营尽管 GAN 领域的进步令人印象深刻,但其在应用过程中仍然存在一些困难。本文梳理了 GAN 在应用过程中存在的一些难题,并提出了最新的解决方法。使用 GAN 的缺陷众所周知,GAN…

java正则表达式获取指定两个字符串之间内容

xml解析利用正则表达式获取指定两个字符串之间内容 在遇到解析复杂xml的时候,想到大家所想到的都是利用dom4j作为首发工具,但是当遇到层次很多,较为复杂,我们难道还需要从根节点一层一层的解析下去吗?此时不仅代码繁琐…

【linux】Matchbox(二):基本概念

X server X server是Linux系统里面图形接口服务器的简称。Windows系统的界面是这个系统不可分割的一部分,各种窗口操作界面显示都是由系统核心直接管理的,而Linux的图形界面并不是系统的必要组成部分,它可以在无界面的条件下运行。当需要Lin…

Android 控件之ImageSwitcher图片切换器

ImageSwitcher是Android中控制图片展示效果的一个控件,如:幻灯片效果...,颇有感觉啊。做相册一绝 源码下载 一、重要方法 setImageURI(Uri uri):设置图片地址 setImageResource(int resid):设置图片资源库 setImageDra…

【Qt】Qt5.x移植后的环境配置(imx6)

1、环境配置脚本如下 #!/bin/shexport QTDIR=/usr/lib/qt5 export QT_QPA_PLATFORM_PLUGIN_PATH=$QTDIR/plugins export QT_QPA_PLATFORM=eglfs:fb=/dev/fb0 export QT_QPA_GENERIC_PLUGINS=evdevtouch:/dev/input/event1 export QT_QPAFONTDIR=/usr/lib/fonts export QML2_IM…

程序员如何避免“滴滴式裁员”悲剧?

作者 | 徐麟转载自数据森麟(ID:shujusenlin)滴滴于2月15日正式发表裁员公告,想必很多互联网人的朋友圈都已经被这条消息刷屏了,其中最常见的莫过于下面这张图了:此图一出,广大互联网吃瓜群众不禁后背发凉&a…

windows服务搭建及命令总结

1、图解FTP服务器搭建(Windows Server 2008) https://wenku.baidu.com/view/803bdc1759eef8c75fbfb361.html?fromsearch https://www.cnblogs.com/john2017/p/6269671.html 2、WindowsServer2008下搭建ApachePHPMySQL https://wenku.baidu.com/view/2e82b99ea1116c175f0e7cd18…

Linux下的CST和UTC时间的区别

在linux中,用date查看时间的时候显示:2008年 12月 17日 星期三 09:04:14 CSTCST China Standard Time UTC8:00 中国沿海时间(北京时间)世界协调时间(Universal Time Coordinated,UTC)GPS 系统中有两种时间区分,一为UTC,另一为LT&a…

Python之父重回决策层,未来如何发展?

作者 | 豌豆花下猫来源 | Python猫(ID:python_cat)春节假期结束了,大家陆续地重回到原来的生活轨道上。假期是一个很好的休息与调节的机会,同时,春节还有辞旧迎新的本意,它是新的轮回的开端。在…

【Android】adb命令总结

1、adb version 显示ADB工具版本 2、adb devices 查询设备&#xff0c;显示设备序列号 3、adb sideload < file_location> 通过USB进行ROM刷机 4、adb install < apk文件路径> 安装APK 5、adb uninstall <软件名> 卸载软件 6、adb push <本地路径>…

MySQL中char与varchar的区别

字符与字节的区别 一个字符由于所使用的字符集的不同&#xff0c;会并存储在一个或多个字节中&#xff0c;所以一个字符占用多少个字节取决于所使用的字符集注意&#xff1a;char与varchar后面接的数据大小为存储的字符数&#xff0c;而不是字节数&#xff08;其实是5.0版本以上…

怎样在Red Hat Enterprise Linux 5.4版本上安装GCC?

注意&#xff1a;如果打算使用GUI的方式安装&#xff0c;需要导入GPG-Key(否则在使用GUI时会出现public key for *.rpm is not installed) 请切换到安装光盘目录下&#xff1a; cd /media 可以看到 RHEL* 的目录&#xff0c;然后切换到这个目录中&#xff1a; cd RHEL* 你需要运…

【C++】mingw32-make+cmake:error: ‘nullptr‘ was not declared in this scope解决方法

###问题 使用cmake成功&#xff08;Configuring done Generating done&#xff09;后&#xff0c;在cmd终端中执行 mingw32-make报错&#xff1a; error: nullptr was not declared in this scope###原因 nullptr是在c11的新内容。编译时&#xff0c;没有添加对C11的支持。 解…

喜得爱女,吴恩达深情撰文:欢迎你来到新世界!

整理 | 琥珀出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;一个月前&#xff0c;吴恩达冷不丁在Twitter放出了重磅消息&#xff1a; “我们的最新‘成果’ Baby Ng 即将诞生&#xff01;2019 年 2 月见面&#xff01;”果然&#xff0c;昨日吴恩达公开了首个小公主降…

FastJson 简单使用

对象、List转JsonUser user new User(); /*JSON 序列化&#xff0c;默认序列化出的JSON字符串中键值对是使用双引号&#xff0c;如果需要单引号的JSON字符串&#xff0c; [eg:String jsonString JSON.toJSONString(map, SerializerFeature.UseSingleQuotes);] *fastjson序…

【数据安全案例】交警计算机系统再遭***,交通违法记录随意删除

根据新浪报道&#xff0c;据新华社10月14日电 利用当网管的机会&#xff0c;破解密码&#xff0c;非法进入交警计算机系统为他人删除车辆交通违法记录牟利。辽宁省鞍山市铁西区检察院透露&#xff0c;当地某公司员工程尚军因涉嫌破坏计算机信息系统罪&#xff0c;已于10月初被依…

开源,还能走多远?

【编者按】在各大厂纷纷拥抱开源的当口&#xff0c;“开源代码面临可持续发展危机”的言论也甚嚣尘上。早期&#xff0c;技术爱好者们“用爱发电”&#xff0c;“他们知道在出问题前&#xff0c;没人会注意到他们&#xff0c;没人会重视他们”。但遗憾的是&#xff0c;很长一段…

使用axis开发web service服务端

一、axis环境搭建 1.安装环境 JDK、Tomcat或Resin、eclipse等. 2.到 http://www.apache.org/dyn/closer.cgi/ws/axis/1_4 下载Axis的jar包 3.将Axis的jar包放入WEB-INF/lib目录下 二、编写web service服务端 1.编写服务 package com.webservice;public class HelloWebservice {…

【Qt】qt打印文件名、函数名、行号

#include <QDebug> #define MyDebug qDebug()<<"[FILE:"<<__FILE__<<",LINE"<<__LINE__<<",FUNC"<<__FUNCTION__<<"]

【Qt】Qt项目常用代码总结

路径 获取当前路径 #include <QCoreApplication> QString appDirPath QCoreApplication::applicationDirPath(); 转换成对应系统路径 返回路径名&#xff0c;使分隔符转换为适合底层操作系统的分隔符。 windows下为“\”; linux下为“/” #include <QDir> a…