如何还原MySQL与Node.js字符集不匹配导致的Unicode Emoji乱码?
还原可行性
完全可以还原,该乱码是典型的多次错误字符编码转换导致的,全程没有信息丢失,逆向转码即可得到原始Emoji。
错误转码的完整流程:
- 原始Emoji是4字节的UTF-8编码,以
utf8_general_ci字符集存储在MySQL中 - Node.js的mysql2库使用
latin1_swedish_ci字符集建立连接时,MySQL会把原本的UTF-8字节流逐字节按照latin1编码转成Unicode字符串返回给Node.js,最终就生成了你看到的乱码。
核心还原逻辑
两步逆向转换即可:
- 把拿到的乱码字符串按latin1编码转回二进制字节流,latin1是单字节编码,字符和字节一一对应,不会丢失信息
- 把得到的二进制字节流按照UTF-8编码重新解析,就能得到原始的Emoji字符
JavaScript实现代码
通用浏览器/Node.js版本
function restoreMojibakeToEmoji(mojibakeStr) { // 按latin1规则把字符串转成字节数组 const bytes = new Uint8Array(mojibakeStr.length); for (let i = 0; i < mojibakeStr.length; i++) { bytes[i] = mojibakeStr.charCodeAt(i) & 0xff; } // 按utf8规则解码字节数组 return new TextDecoder('utf-8').decode(bytes); } // 测试你提供的样例 console.log(restoreMojibakeToEmoji('├░┬č┬Ź┬ć')); console.log(restoreMojibakeToEmoji('├░┬č┬ĺ┬Ž')); console.log(restoreMojibakeToEmoji('├░┬č┬ś┬ł')); console.log(restoreMojibakeToEmoji('├░┬č┬ą┬Á'));
Node.js专属简化版本
function restoreMojibakeToEmoji(mojibakeStr) { return Buffer.from(mojibakeStr, 'latin1').toString('utf8'); }
根因修复方案
如果要避免后续再出现该问题,直接把mysql2连接配置的字符集参数改为utf8mb4即可,不需要额外做转码处理。
内容的提问来源于stack exchange,提问作者ElSajko
相关产品推荐
相关产品推荐

