Javascript十六进制到二进制使用UTF8


Javascript hexadecimal to binary using UTF8

我在SQLite数据库中存储的数据为BINARY(16),其值由PHPhex2bin函数在32位十六进制字符串上确定。

例如,字符串434e405b823445c09cb6c359fb1b7918返回CN@[4EÀ¶ÃYûy

存储在此数据库中的数据需要由JavaScript操作,为此,我使用了以下函数(改编自Andris的回答):

// Convert hexadecimal to binary string
String.prototype.hex2bin = function ()
{
    // Define the variables
    var i = 0, l = this.length - 1, bytes = []
    // Iterate over the nibbles and convert to binary string
    for (i; i < l; i += 2)
    {
        bytes.push(parseInt(this.substr(i, 2), 16))
    }
    // Return the binary string
    return String.fromCharCode.apply(String, bytes)
}

按预期工作,从434e405b823445c09cb6c359fb1b7918返回CN@[4EÀ¶ÃYûy

我的问题是,然而,当直接处理由PHPhex2bin函数返回的数据时,我得到的是字符串CN@[�4E����Y�y而不是CN@[4EÀ¶ÃYûy。这使得我不可能在两者之间工作(上下文中,JavaScript被用来为一个离线iPad应用程序供电,该应用程序与从PHP web应用程序检索的数据一起工作),因为我需要能够使用JavaScript生成一个32个字符的十六进制字符串,将其转换为二进制字符串,并使其与PHPhex2bin函数(和SQLiteHEX函数)一起工作。

我认为,这个问题是JavaScript使用UTF-16,而二进制字符串存储为utf8_unicode_ci。然后,我最初的想法是,我需要将字符串转换为UTF-8。通过谷歌搜索我找到了这里,通过StackOverflow搜索我找到了bobince的答案,两者都推荐使用unescape(encodeURIComponent(str))。然而,这确实返回了我需要的(CN@[�4E����Y�y):

// CN@[Â4EöÃYûy
unescape(encodeURIComponent('434e405b823445c09cb6c359fb1b7918'.hex2bin()))

我的问题是:

如何使用JavaScript将十六进制字符串转换为UTF-8二进制字符串?

给定一个十六进制编码的UTF-8字符串,' hex',

hex.replace(/../g, '%$&')

将生成uri编码的UTF-8字符串。

decodeURIComponent将uri编码的UTF-8序列转换为JavaScript的UTF-16编码字符串,因此

decodeURIComponent(hex.replace(/../g, '%$&'))

应该解码一个正确的十六进制编码的UTF-8字符串。

您可以通过将它应用到hex2bin文档中的示例中看到它是有效的。

alert(decodeURIComponent('6578616d706c65206865782064617461'.replace(/../g, '%$&')));
// alerts "example hex data"

你给出的字符串不是UTF-8编码的。具体地说,

434e405b823445c09cb6c359fb1b7918
        ^

82必须至少前两位被设置,而5b不是这样的字节。

RFC 2279解释:

下表总结了这些不同的八位字节类型的格式。字母x表示UCS-4可用于编码的位字符值。

UCS-4 range (hex.)           UTF-8 octet sequence (binary)
0000 0000-0000 007F   0xxxxxxx
0000 0080-0000 07FF   110xxxxx 10xxxxxx
0000 0800-0000 FFFF   1110xxxx 10xxxxxx 10xxxxxx

您的应用程序在任何时候都不必处理二进制文件。插入是最近可能的点,那就是你最后转换成二进制。选择是最早可能的点,这是您转换为十六进制并使用十六进制字符串在整个应用程序。

插入时,可以用blob字面值替换UNHEX:

INSERT INTO table (id)
VALUES (X'434e405b823445c09cb6c359fb1b7918')

选择时,可以HEX:

SELECT HEX(id) FROM table

根据Mike的回答,这里有一些编码和解码的代码。

注意escape/unescape()函数已被弃用。如果您需要填充它们,您可以查看更全面的UTF-8编码示例:http://jsfiddle.net/47zwb41o

// UTF-8 to hex
var utf8ToHex = function( s ){
    s = unescape( encodeURIComponent( s ) );
    var chr, i = 0, l = s.length, out = '';
    for( ; i < l; i++ ){
        chr = s.charCodeAt( i ).toString( 16 );
        out += ( chr.length % 2 == 0 ) ? chr : '0' + chr;
    }
    return out;
};
// Hex to UTF-8
var hexToUtf8 = function( s ){
    return decodeURIComponent( s.replace( /../g, '%$&' ) );
};