问题:
关于Ios客户端在输入框输入表情符号引起crash问题分析:
1、由于IOS4.X 、IOS5.X 、 IOS6.X 等的表情符号采用的是unicode6 和softbank 等编码格式,该格式为4字节,;但服务器端数据库采用的是UTF-8 编码,只支持1-3个字节,两者编码格式不适引起的存储错误。
解决办法以及利弊:
1.服务器端转换数据库存储编码
数据库目前采用的编码为UTF8, 转换为可支持4个字节的utf8mb4_unicode编码。
利:客户端存储和请求数据的时候不需要都去做转换
弊:1)转换编码格式可能会导致现有数据库的数据发生乱码;
2)转换编码格式之后,可能对后续的全文搜索功能有影响,大多数中文搜索引擎支持的编码格式为UTF-8;
3)若Android端的编码与数据库转换后的编码不符,将对Android端产生同样的问题。
2. 客户端转换编码
客户端输入内容时候,统一存储为服务端数据库支持的编码;户端请求内容的时候,需要根据客户端支持的编码对请求到的数据进行相应的转换,如:ios4采用softbank编码做替换,ios5采用unicode编码直接支持。
利:减少服务器端转换编码带来的风险和压力
弊:客户端需要根据不同的设备系统自行做编码转换
解决办法:
经过测试,如果原数据库编码为utf8,使用如下步骤,可以在本地机器成功保存IOS8自带输入法中的表情符号到数据库,但是在197服务器上改变编码之后mysql的服务不能启动。
1. 备份数据库
2. 升级mysql到5.5.3以上的版本
3. 修改数据库、数据表、字段的字符集编码和校验编码为utf8mb4
a) 修改数据库编码: ALTER DATABASE database_name CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
b) 修改数据表编码: ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
c) 修改字段编码: ALTER TABLE table_name CHANGE column_name column_name VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
其中在b)和c)两步之前,如果表中有历史数据,字段数据类型为VARCHAR(255), 并且该字段的历史数据的字符长度超过191,则需要先把该字段的数据类型修改为可以保存更大长度的。
这是因为使用utf8mb4编码后,一个原utf8编码中的VARCHAR(255) 的字段,最多只能保存utf8mbs编码下的191个字符。
同理,如果待转换的数据表上创建有索引,并且索引名字超过了191个字符,则需要把索引名字修改为191个字符以下。
4. 修改mysql server的配置文件
配置文件mysql.ini (Windows下默认路径为C:\ProgramData\MySQL\MySQL Server 5.5 ,Linux下为/etc/mysql.cnf)中加入或者修改以下内容:
[client]
default-character-set = utf8mb4
[mysql]
default-character-set = utf8mb4
[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
1. 备份数据库
2. 升级mysql到5.5.3以上的版本
3. 修改数据库、数据表、字段的字符集编码和校验编码为utf8mb4
a) 修改数据库编码: ALTER DATABASE database_name CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
b) 修改数据表编码: ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
c) 修改字段编码: ALTER TABLE table_name CHANGE column_name column_name VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
其中在b)和c)两步之前,如果表中有历史数据,字段数据类型为VARCHAR(255), 并且该字段的历史数据的字符长度超过191,则需要先把该字段的数据类型修改为可以保存更大长度的。
这是因为使用utf8mb4编码后,一个原utf8编码中的VARCHAR(255) 的字段,最多只能保存utf8mbs编码下的191个字符。
同理,如果待转换的数据表上创建有索引,并且索引名字超过了191个字符,则需要把索引名字修改为191个字符以下。
4. 修改mysql server的配置文件
配置文件mysql.ini (Windows下默认路径为C:\ProgramData\MySQL\MySQL Server 5.5 ,Linux下为/etc/mysql.cnf)中加入或者修改以下内容:
[client]
default-character-set = utf8mb4
[mysql]
default-character-set = utf8mb4
[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
5.修改mysql安装路径下的(....\MySQL Server 5.5\share\charsets\index.xml)\share\charsets\index.xml 文件。(这一步骤可改可不改)
将如下代码复制一份:
<charset name="utf8">
<family>Unicode</family>
<description>UTF-8 Unicode</description>
<alias>utf-8</alias>
<collation name="utf8_general_ci"id="33">
<flag>primary</flag>
<flag>compiled</flag>
</collation>
<collation name="utf8_bin"id="83">
<flag>binary</flag>
<flag>compiled</flag>
</collation>
</charset>
<family>Unicode</family>
<description>UTF-8 Unicode</description>
<alias>utf-8</alias>
<collation name="utf8_general_ci"id="33">
<flag>primary</flag>
<flag>compiled</flag>
</collation>
<collation name="utf8_bin"id="83">
<flag>binary</flag>
<flag>compiled</flag>
</collation>
</charset>
修改成如下,保存即可:
<charset name="utf8mb4">
<family>Unicode</family>
<description>UTF-8 Unicode</description>
<alias>utf-8</alias>
<collation name="utf8_general_ci"id="33">
<flag>primary</flag>
<flag>compiled</flag>
</collation>
<collation name="utf8_bin"id="83">
<flag>binary</flag>
<flag>compiled</flag>
</collation>
</charset>
<family>Unicode</family>
<description>UTF-8 Unicode</description>
<alias>utf-8</alias>
<collation name="utf8_general_ci"id="33">
<flag>primary</flag>
<flag>compiled</flag>
</collation>
<collation name="utf8_bin"id="83">
<flag>binary</flag>
<flag>compiled</flag>
</collation>
</charset>
按上述1、2、3、4、5步奏修改后需重启mysql 服务,在客户端执行该命令:SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci
6. 在web应用服务器(tomcate、jetty、resin等)连接mysql服务器的jdbc连接中,加入连接参数,(?之后的内容):
jdbc:mysql://localhost:3306/项目名?autoConnect=true&useUnicode=true&characterEncoding=utf-8
7. 更换web应用服务器(tomcate、jetty、resin等)和web应用lib文件夹下的mysql的jdbc驱动版本, 使用5.1.31或以上。
经过这些步骤之后,在本地机器(Windows 7)上测试,IOS8可以输入自带输入法中的表情符号,保存到数据库并读取。