Java String.getBytes(“UTF8”)JavaScript模拟

时间:2012-09-20 18:39:05

标签: java javascript string utf-8 byte

Bytes to string and backward

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

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

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

4 个答案:

答案 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)

TextEncoderEncoding 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;  
}