JavaScript中的Unicode和URI编码、解码和转义
如果你看这个,它有一个Unicode字符的转义序列列表,实际上对我不起作用 例如,对于“%96”,它应该是–,我在尝试解码时出错:JavaScript中的Unicode和URI编码、解码和转义,javascript,unicode,urlencode,encode,utf-8,Javascript,Unicode,Urlencode,Encode,Utf 8,如果你看这个,它有一个Unicode字符的转义序列列表,实际上对我不起作用 例如,对于“%96”,它应该是–,我在尝试解码时出错: decodeURIComponent("%96"); URIError: URI malformed 如果我尝试编码“–”,我实际上得到: encodeURIComponent("–"); "%E2%80%93" 我在互联网上搜索了一下,我看到了,其中提到使用escape和unescape分别与decodeURIComponent和encodeURICompon
decodeURIComponent("%96");
URIError: URI malformed
如果我尝试编码“–”,我实际上得到:
encodeURIComponent("–");
"%E2%80%93"
我在互联网上搜索了一下,我看到了,其中提到使用escape和unescape分别与decodeURIComponent和encodeURIComponent一起使用。这似乎没有什么帮助,因为无论我做什么尝试,%96都不会显示为“–”,这当然行不通:
decodeURIComponent(escape("%96));
"%96"
不是很有帮助
我怎样才能使“%96”成为一个带有JavaScript的“–”(而不必为我可能遇到的每个可能的unicode字符硬编码映射) 具体见:
有一种特殊的“%unnn”格式
编码Unicode UTF-16码点,
而不是编码UTF-8字节
我怀疑“–”是其中一个字符,因为它来自卡尔·亨德森(Carl Henderson)的“构建可伸缩的网站”,所以在isā中以社区维基条目的形式发布0x96。不过,这本书说,可以复制示例的重要部分。您可以使用它为“-”创建一个特例
函数escape\u utf8(数据){
如果(数据=''| |数据==null){
返回“”;
}
data=data.toString();
var缓冲区=“”;
对于(变量i=0;i 0x10000){
//4字节
bs[0]=0xF0 |((c&0x1C0000)>>>18);
bs[1]=0x80 |((c&0x3F000)>>>12);
bs[2]=0x80 |((c&0xFC0)>>>6);
bs[3]=0x80 |(c&0x3F);
}否则,如果(c>0x800){
//3字节
bs[0]=0xE0 |((c&0xF000)>>>12);
bs[1]=0x80 |((c&0xFC0)>>>6);
bs[2]=0x80 |(c&0x3F);
}否则,如果(c>0x80){
//2字节
bs[0]=0xC0 |((c&0x7C0)>>>6);
bs[1]=0x80 |(c&0x3F);
}否则{
//1字节
bs[0]=c;
}
对于(var j=0;j>>4)
+半字节到十六进制(b&0x0F);缓冲区+='%'+hex;
}
}
返回缓冲区;
}
函数半字节到十六进制(半字节){
var chars='0123456789ABCDEF';
返回字符(半字节);
}
URI中的序列%XX
编码一个“八位字节”,即八位字节。这就提出了一个问题,即解码字节指的是什么Unicode字符。如果我的记忆正确的话,在旧版本的URI规范中,并没有很好地定义假定的字符集。在URI规范的更高版本中,建议将UTF-8作为默认编码字符集。也就是说,要解码一个字节序列,您需要解码每个%XX
序列,然后使用UTF-8字符集将结果字节转换为字符串
这解释了为什么%96
无法解码。十六进制0x96值不是有效的UTF-8序列。因为它超出了ASCII,所以在它前面需要一个特殊的修饰符字节来表示扩展字符。(有关更多详细信息,请参阅UTF-8规范。)JavaScriptencodeURIComponent()
和decodeURIComponent()
方法都采用UTF-8(正如它们应该的那样),因此我不希望%96
正确解码
您引用的字符是U+2013,一个en破折号。你引用的页面究竟是如何从十六进制0x96(十进制150)中得到一个破折号的?他们显然没有采用UTF-8编码,这是标准。它们不采用ASCII,ASCII不包含此字符。他们甚至没有假设,这是一种标准编码,每个字符使用一个字节。事实证明,他们假设的是特殊的代码页。也就是说,您试图解码的URI假设用户在Windows机器上,更糟糕的是,在英语(或其他几种西方语言之一)的Windows机器上
简而言之,你用的桌子不好。它已过时,并假定用户使用的是英文Windows系统。对非ASCII值进行编码的最新正确方法是将其转换为UTF-8,然后使用
%XX
对每个八位字节进行编码。这就是为什么在尝试对字符编码时得到了%E2%80%93
,而这正是decodeURIComponent()
所期望的。您正在使用的URI编码不正确。如果没有其他选择,您可以猜测URI使用的是Windows 1252,自己转换字节,然后使用Windows 1252表找出Unicode值的用途。但这很危险——您如何知道哪个URI使用哪个表?这就是为什么每个人都选择UTF-8。如果可能,请告诉给您这些URI的人正确编码它们。我不确定这有什么帮助,因为我正在尝试将%nn格式转换为unicode,而不是相反。我想您可以在使用decodeURIComponent在javascript中对其进行解码之前,将“-”替换为“%E2%80%93”,但它可能会有副作用,所以我不知道。不幸的是,我无法控制espace进程,它是一个野生的字符串。我只需要能够在所有情况下处理“%nn”格式。如果代码是单个的“%nn”“代码您确定源数据是用Unicode编码的,而不是ASCII/Latin-1等吗?decode/encodeUri组件可能使用当前页面的编码,我假设在您的示例中是UTF-8。如果是这样的话,这可能是一个黑客攻击,但您可以使用另一个IFrame,使用不同的编码与父级或类似的方式进行通信,作为最后的手段。或者,您可以使用从另一个编码到Unicode的表,并通过拆分“%”字符或类似的内容进行解码,然后自己处理。只是一些建议:-)escape(“–”)创建“%u2013”。这仍然不能解释我遇到%96时如何处理%96
function escape_utf8(data) {
if (data == '' || data == null){
return '';
}
data = data.toString();
var buffer = '';
for(var i=0; i<data.length; i++){
var c = data.charCodeAt(i);
var bs = new Array();
if (c > 0x10000){
// 4 bytes
bs[0] = 0xF0 | ((c & 0x1C0000) >>> 18);
bs[1] = 0x80 | ((c & 0x3F000) >>> 12);
bs[2] = 0x80 | ((c & 0xFC0) >>> 6);
bs[3] = 0x80 | (c & 0x3F);
}else if (c > 0x800){
// 3 bytes
bs[0] = 0xE0 | ((c & 0xF000) >>> 12);
bs[1] = 0x80 | ((c & 0xFC0) >>> 6);
bs[2] = 0x80 | (c & 0x3F);
}else if (c > 0x80){
// 2 bytes
bs[0] = 0xC0 | ((c & 0x7C0) >>> 6);
bs[1] = 0x80 | (c & 0x3F);
}else{
// 1 byte
bs[0] = c;
}
for(var j=0; j<bs.length; j++){
var b = bs[j];
var hex = nibble_to_hex((b & 0xF0) >>> 4)
+ nibble_to_hex(b &0x0F);buffer += '%'+hex;
}
}
return buffer;
}
function nibble_to_hex(nibble){
var chars = '0123456789ABCDEF';
return chars.charAt(nibble);
}