4

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

例如,字符串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)

}

这按预期工作,CN@[4EÀ¶ÃYûy434e405b823445c09cb6c359fb1b7918.

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

我相信这个问题是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二进制字符串?

4

3 回答 3

2

给定一个十六进制编码的 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
于 2013-03-18T17:06:46.343 回答
1

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

插入时,您可以替换UNHEX为 blob 文字:

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

选择时,您可以HEX

SELECT HEX(id) FROM table
于 2013-03-18T19:18:15.850 回答
0

扩展迈克的答案,这里有一些编码和解码的代码。

请注意,这些escape/unescape()功能已弃用。如果你需要 polyfills,你可以在这里查看更全面的 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, '%$&' ) );
};
于 2017-01-18T06:43:38.063 回答