在那里写的函数正常工作,pack(unpack("string"))
产生"string"
。但我希望得到与"string".getBytes("UTF8")
给出的相同的结果。
问题是如何使一个函数在JavaScript中提供与Java getBytes(“UTF8”)相同的功能?
对于上述文章中的拉丁字符串unpack(str)
提供的结果与getBytes("UTF8")
相同,只是它为奇数位置添加了0
。但是对于非拉丁字符串,它在我看来完全不同。有没有办法像Java一样使用JavaScript中的字符串数据?
答案 0 :(得分:7)
您无需编写全功能的UTF-8编码器;有一个更容易的JS习惯用法将Unicode字符串转换为代表UTF-8代码单元的字节串:
unescape(encodeURIComponent(str))
(这是有效的,因为escape
/ unescape
使用的奇数编码使用%xx
十六进制序列来表示带有该代码的ISO-8859-1字符,而不是使用的UTF-8通过URI组件转义。同样decodeURIComponent(escape(bytes))
向另一个方向发展。)
因此,如果你想要一个数组,它将是:
function toUTF8Array(str) {
var utf8= unescape(encodeURIComponent(str));
var arr= new Array(utf8.length);
for (var i= 0; i<utf8.length; i++)
arr[i]= utf8.charCodeAt(i);
return arr;
}
答案 1 :(得分:3)
您可以使用此功能(gist):
function toUTF8Array(str) {
var utf8 = [];
for (var i=0; i < str.length; i++) {
var charcode = str.charCodeAt(i);
if (charcode < 0x80) utf8.push(charcode);
else if (charcode < 0x800) {
utf8.push(0xc0 | (charcode >> 6),
0x80 | (charcode & 0x3f));
}
else if (charcode < 0xd800 || charcode >= 0xe000) {
utf8.push(0xe0 | (charcode >> 12),
0x80 | ((charcode>>6) & 0x3f),
0x80 | (charcode & 0x3f));
}
else {
// let's keep things simple and only handle chars up to U+FFFF...
utf8.push(0xef, 0xbf, 0xbd); // U+FFFE "replacement character"
}
}
return utf8;
}
使用示例:
>>> toUTF8Array("中€")
[228, 184, 173, 226, 130, 172]
如果你想要超过127的值的负数,就像Java的byte-to-int转换一样,你必须调整常量并使用
utf8.push(0xffffffc0 | (charcode >> 6),
0xffffff80 | (charcode & 0x3f));
和
utf8.push(0xffffffe0 | (charcode >> 12),
0xffffff80 | ((charcode>>6) & 0x3f),
0xffffff80 | (charcode & 0x3f));
答案 2 :(得分:2)
TextEncoder
是Encoding Living Standard的一部分,根据Chromium Dashboard的Encoding API条目,它在Firefox中提供,并将在Chrome 38中发布。还有一个{{3} polyfill可用于其他浏览器。
下面的JavaScript代码示例会返回一个填充了您期望的值的Uint8Array
。
(new TextEncoder()).encode("string")
// [115, 116, 114, 105, 110, 103]
一个更有趣的例子,更好的显示UTF-8用in
替换string
中的îñ
:
(new TextEncoder()).encode("strîñg")
[115, 116, 114, 195, 174, 195, 177, 103]
答案 3 :(得分:0)
以下函数将处理U + FFFF以上的那些。
因为javascript文本是UTF-16,所以在字符串中使用两个“字符”来表示BMP之上的字符,而charCodeAt返回相应的代理代码。 fixedCharCodeAt处理这个。
function encodeTextToUtf8(text) {
var bin = [];
for (var i = 0; i < text.length; i++) {
var v = fixedCharCodeAt(text, i);
if (v === false) continue;
encodeCharCodeToUtf8(v, bin);
}
return bin;
}
function encodeCharCodeToUtf8(codePt, bin) {
if (codePt <= 0x7F) {
bin.push(codePt);
} else if (codePt <= 0x7FF) {
bin.push(192 | (codePt >> 6), 128 | (codePt & 63));
} else if (codePt <= 0xFFFF) {
bin.push(224 | (codePt >> 12),
128 | ((codePt >> 6) & 63),
128 | (codePt & 63));
} else if (codePt <= 0x1FFFFF) {
bin.push(240 | (codePt >> 18),
128 | ((codePt >> 12) & 63),
128 | ((codePt >> 6) & 63),
128 | (codePt & 63));
}
}
function fixedCharCodeAt (str, idx) {
// ex. fixedCharCodeAt ('\uD800\uDC00', 0); // 65536
// ex. fixedCharCodeAt ('\uD800\uDC00', 1); // 65536
idx = idx || 0;
var code = str.charCodeAt(idx);
var hi, low;
if (0xD800 <= code && code <= 0xDBFF) { // High surrogate (could change last hex to 0xDB7F to treat high private surrogates as single characters)
hi = code;
low = str.charCodeAt(idx+1);
if (isNaN(low)) {
throw(encoding_error.invalid_surrogate_pair.replace('%pos%', idx));
}
return ((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000;
}
if (0xDC00 <= code && code <= 0xDFFF) { // Low surrogate
// We return false to allow loops to skip this iteration since should have already handled high surrogate above in the previous iteration
return false;
/*hi = str.charCodeAt(idx-1);
low = code;
return ((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000;*/
}
return code;
}