Javascript:unicode 字符到基于 BYTE 的十六进制转义序列(不是代理项)
Javascript: unicode character to BYTE based hex escape sequence (NOT surrogates)
在 javascript 中,我正在尝试将 unicode 转换为与 C:
兼容的基于字节的十六进制转义序列
即。 </code></p>
<p>变为:<code>\xF0\x9F\x98\x84
(正确)
不是 javascript 代理人,不是 \uD83D\uDE04
(错误)
我无法弄清楚 C 想要的四个字节与 javascript 使用的两个代理项之间的数学关系。我怀疑该算法比我微弱的尝试复杂得多。
感谢任何提示。
您的 C 代码需要一个 UTF-8 string (the symbol is represented as 4 bytes). The JS representation you see is UTF-16 但是(该符号表示为 2 uint16
s,一个代理对)。
您首先需要获取符号的 (Unicode) 代码点(来自 UTF-16 JS 字符串),然后从中构建它的 UTF-8 表示。
从 ES6 开始,您可以在第一部分使用 codePointAt
method,即使不支持,我也建议将其用作 shim。我猜你不想自己解码代理对:-)
至于其他的,我认为没有库方法,但是你可以自己写 according 到规范:
function hex(x) {
x = x.toString(16);
return (x.length > 2 ? "\u0000" : "\x00").slice(0,-x.length)+x.toUpperCase();
}
var c = "";
console.log(c.length, hex(c.charCodeAt(0))+hex(c.charCodeAt(1))); // 2, "\uD83D\uDE04"
var cp = c.codePointAt(0);
var bytes = new Uint8Array(4);
bytes[3] = 0x80 | cp & 0x3F;
bytes[2] = 0x80 | (cp >>>= 6) & 0x3F;
bytes[1] = 0x80 | (cp >>>= 6) & 0x3F;
bytes[0] = 0xF0 | (cp >>>= 6) & 0x3F;
console.log(Array.prototype.map.call(bytes, hex).join("")) // "\xf0\x9f\x98\x84"
(在Chrome测试)
在这里找到了解决方案:http://jonisalonen.com/2012/from-utf-16-to-utf-8-in-javascript/
我永远也想不通那个数学,哇。
稍微缩小了
function UTF8seq(s) {
var i,c,u=[];
for (i=0; i < s.length; i++) {
c = s.charCodeAt(i);
if (c < 0x80) { u.push(c); }
else if (c < 0x800) { u.push(0xc0 | (c >> 6), 0x80 | (c & 0x3f)); }
else if (c < 0xd800 || c >= 0xe000) { u.push(0xe0 | (c >> 12), 0x80 | ((c>>6) & 0x3f), 0x80 | (c & 0x3f)); }
else { i++; c = 0x10000 + (((c & 0x3ff)<<10) | (s.charCodeAt(i) & 0x3ff));
u.push(0xf0 | (c >>18), 0x80 | ((c>>12) & 0x3f), 0x80 | ((c>>6) & 0x3f), 0x80 | (c & 0x3f)); }
}
for (i=0; i < u.length; i++) { u[i]=u[i].toString(16); }
return '\x'+u.join('\x');
}
encodeURIComponent 是否有效:
var input = "\uD83D\uDE04";
var result = encodeURIComponent(input).replace(/%/g, "\x"); // \xF0\x9F\x98\x84
Upd: 其实C字符串可以包含数字和字母不用转义,但是如果真的需要转义的话:
function escape(s, escapeEverything) {
if (escapeEverything) {
s = s.replace(/[\x10-\x7f]/g, function (s) {
return "-x" + s.charCodeAt(0).toString(16).toUpperCase();
});
}
s = encodeURIComponent(s).replace(/%/g, "\x");
if (escapeEverything) {
s = s.replace(/\-/g, "\");
}
return s;
}
在 javascript 中,我正在尝试将 unicode 转换为与 C:
兼容的基于字节的十六进制转义序列即。 </code></p>
<p>变为:<code>\xF0\x9F\x98\x84
(正确)
不是 javascript 代理人,不是 \uD83D\uDE04
(错误)
我无法弄清楚 C 想要的四个字节与 javascript 使用的两个代理项之间的数学关系。我怀疑该算法比我微弱的尝试复杂得多。
感谢任何提示。
您的 C 代码需要一个 UTF-8 string (the symbol is represented as 4 bytes). The JS representation you see is UTF-16 但是(该符号表示为 2 uint16
s,一个代理对)。
您首先需要获取符号的 (Unicode) 代码点(来自 UTF-16 JS 字符串),然后从中构建它的 UTF-8 表示。
从 ES6 开始,您可以在第一部分使用 codePointAt
method,即使不支持,我也建议将其用作 shim。我猜你不想自己解码代理对:-)
至于其他的,我认为没有库方法,但是你可以自己写 according 到规范:
function hex(x) {
x = x.toString(16);
return (x.length > 2 ? "\u0000" : "\x00").slice(0,-x.length)+x.toUpperCase();
}
var c = "";
console.log(c.length, hex(c.charCodeAt(0))+hex(c.charCodeAt(1))); // 2, "\uD83D\uDE04"
var cp = c.codePointAt(0);
var bytes = new Uint8Array(4);
bytes[3] = 0x80 | cp & 0x3F;
bytes[2] = 0x80 | (cp >>>= 6) & 0x3F;
bytes[1] = 0x80 | (cp >>>= 6) & 0x3F;
bytes[0] = 0xF0 | (cp >>>= 6) & 0x3F;
console.log(Array.prototype.map.call(bytes, hex).join("")) // "\xf0\x9f\x98\x84"
(在Chrome测试)
在这里找到了解决方案:http://jonisalonen.com/2012/from-utf-16-to-utf-8-in-javascript/
我永远也想不通那个数学,哇。
稍微缩小了
function UTF8seq(s) {
var i,c,u=[];
for (i=0; i < s.length; i++) {
c = s.charCodeAt(i);
if (c < 0x80) { u.push(c); }
else if (c < 0x800) { u.push(0xc0 | (c >> 6), 0x80 | (c & 0x3f)); }
else if (c < 0xd800 || c >= 0xe000) { u.push(0xe0 | (c >> 12), 0x80 | ((c>>6) & 0x3f), 0x80 | (c & 0x3f)); }
else { i++; c = 0x10000 + (((c & 0x3ff)<<10) | (s.charCodeAt(i) & 0x3ff));
u.push(0xf0 | (c >>18), 0x80 | ((c>>12) & 0x3f), 0x80 | ((c>>6) & 0x3f), 0x80 | (c & 0x3f)); }
}
for (i=0; i < u.length; i++) { u[i]=u[i].toString(16); }
return '\x'+u.join('\x');
}
encodeURIComponent 是否有效:
var input = "\uD83D\uDE04";
var result = encodeURIComponent(input).replace(/%/g, "\x"); // \xF0\x9F\x98\x84
Upd: 其实C字符串可以包含数字和字母不用转义,但是如果真的需要转义的话:
function escape(s, escapeEverything) {
if (escapeEverything) {
s = s.replace(/[\x10-\x7f]/g, function (s) {
return "-x" + s.charCodeAt(0).toString(16).toUpperCase();
});
}
s = encodeURIComponent(s).replace(/%/g, "\x");
if (escapeEverything) {
s = s.replace(/\-/g, "\");
}
return s;
}