我在SQLite
数据库中存储的数据为BINARY(16)
,其值由PHP
的hex2bin
函数在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
。
我的问题是,然而,当直接处理由PHP
的hex2bin
函数返回的数据时,我得到的是字符串CN@[�4E����Y�y
而不是CN@[4EÀ¶ÃYûy
。这使得我不可能在两者之间工作(上下文中,JavaScript
被用来为一个离线iPad应用程序供电,该应用程序与从PHP
web应用程序检索的数据一起工作),因为我需要能够使用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
二进制字符串?
给定一个十六进制编码的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, '%$&' ) );
};