将 astral 字符的 UTF16 转换为 UTF8

Inverting UTF16 to UTF8 conversion for astral characters

我的问题很简单。从一个不在基本多语言平面中的字符开始,比如 var original = "" 或等效的

var original=`\u{1f3ae}`

Javascript通过UTF-16编码将这个字符串存储在内存中。不幸的是,您将字符串提供给某些 database/application (具体无关紧要)并且它错误地将 UTF-16 字节解释为 UTF-8 字节,并且当您从 database/application 中读出字符串时它实际上是什么给你的正是

var switchedEncoding = Buffer.from(original, 'utf16le').toString('utf8')

如果您在这种情况下记录 switchedEncoding,您将得到 <خ�。不好。好的,所以您尝试将其切换回来:

var switchedBack = Buffer.from(switchedEncoding,'utf8').toString('utf16le')

如果您在这种情况下记录 switchedBack,您会得到 �붿 而不是 </code>。无赖。</p> <p>另一方面,如果您的原始字符串在 BMP 中,<code>switchedBack 可以很好地恢复原始字符串。我的问题是 application/database 进行的不正确解码是否会不可逆转地丢失信息?如果没有,我想要一个聪明的功能,即使对于星界中的角色也可以将其反转。

感谢您的帮助!

回答如下。我可以让数据库(leveldb)将内容读入缓冲区,然后我使用节点中的 iconv 包使用以下方法:

const Iconv = require("iconv").Iconv;
let iconv = new Iconv("UTF-8","UTF-16LE");
let iconv2 = new Iconv("UTF-16LE","UTF-8");
let original = "\u{1f3ae}"
let switched = iconv.convert(original)
let switchedBack = iconv2.convert(switched)
console.log(original)
console.log(switched.toString())
console.log(switchedBack.toString())


// So it's the switched.toString() which is not recoverable; 
// switched itself (a Buffer) is;

很高兴知道如果缓冲区中字节的编码不是 someEncodingBuffer.toString('someEncoding') 并不总是可逆的。