背景:
移动web前端textarea输入框输入emoji表情,用oracle数据库保存变成了“?”
思路:
oracle默认是 UTF-8 编码存储数据的。而 emoji 表情是 UTF-16 编码的,这样就导致数据库存储 emoji 表情数据报错(使用UTF-8编码格式存储)。所以我们可以从后端和前端两个方面修改。
后端:修改数据库编码格式
前端:把表情转换成 UTF-8 编码,页面呈现时再解码
代码:
添加留言时:检测表情并转码
let reg = /[\ud800-\udbff][\udc00-\udfff]/g; // emoji 表情正则
/**
* @description: 表情转码
* @param {String} str 要转化的字符串
* @return {String} 转化字符串
*/
function utf16ToEntities(str) {
const reg = /[\ud800-\udbff][\udc00-\udfff]/g; // 检测utf16字符正则
str = str.replace(reg, (char) => {
let H, L, code, s;
if (char.length === 2) {
H = char.charCodeAt(0); // 取出高位
L = char.charCodeAt(1); // 取出低位
code = (H - 0xD800) * 0x400 + 0x10000 + L - 0xDC00; // 转换算法
s = `&#${code};`;
} else {
s = char;
}
return s;
});
return str;
}
呈现留言时:对表情解码
/**
* @description: 表情解码
* @param {String} str
* @return {*}
*/
function entitiesToUtf16(str) {
const reg = /&#\d+;/g;
const arr = str.match(reg) || [];
let H, L, code;
for (let i = 0; i < arr.length; i += 1) {
code = arr[i];
code = code.replace('&#', '').replace(';', '');
// 高位
H = Math.floor((code - 0x10000) / 0x400) + 0xD800;
// 低位
L = ((code - 0x10000) % 0x400) + 0xDC00;
code = `&#${code};`;
const s = String.fromCharCode(H, L);
str = str.replace(code, s);
}
return str;
}