4

字节到字符串和向后

在那里编写的函数可以正常工作,即pack(unpack("string"))产生"string". 但我希望"string".getBytes("UTF8")得到与 Java 相同的结果。

问题是如何使一个函数在 JavaScript 中提供与 Java getBytes("UTF8") 相同的功能?

对于上面提到的文章中的拉丁字符串,除了为奇数位置添加之外,它unpack(str)提供了相同的结果。但是对于非拉丁字符串,它在我看来完全不同。有没有办法像 Java 一样在 JavaScript 中处理字符串数据?getBytes("UTF8")0

4

4 回答 4

7

您无需编写完整的 UTF-8 编码器;有一个更简单的 JS 习惯用法可以将 Unicode 字符串转换为表示 UTF-8 代码单元的字节字符串:

unescape(encodeURIComponent(str))

(这是有效的,因为escape/unescape使用的奇数编码使用%xx十六进制序列来表示带有该代码的 ISO-8859-1 字符,而不是 URI 组件转义使用的 UTF-8。类似地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;
}
于 2013-11-30T17:37:07.900 回答
3

您可以使用此功能(要点):

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 的字节到整数转换一样,你必须调整常量并使用

            utf8.push(0xffffffc0 | (charcode >> 6), 
                      0xffffff80 | (charcode & 0x3f));

            utf8.push(0xffffffe0 | (charcode >> 12), 
                      0xffffff80 | ((charcode>>6) & 0x3f), 
                      0xffffff80 | (charcode & 0x3f));
于 2012-09-21T10:37:24.367 回答
3

TextEncoderEncoding Living Standard的一部分,根据 Chromium Dashboard 的Encoding API条目,它在 Firefox 中发布,并将在 Chrome 38 中发布。还有一个文本编码polyfill 可用于其他浏览器。

下面的 JavaScript 代码示例返回一个Uint8Array填充了您期望的值。

(new TextEncoder()).encode("string") 
// [115, 116, 114, 105, 110, 103]

一个更有趣的例子表明 UTF-8 将ininstring替换为îñ

(new TextEncoder()).encode("strîñg")
[115, 116, 114, 195, 174, 195, 177, 103]
于 2014-09-01T03:55:30.103 回答
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;  
}  
于 2013-01-22T08:35:31.910 回答