我正在创建一个javascript应用程序,它使用jquery检索.json
个文件,并将数据注入其嵌入的网页中。
.json
文件采用UTF-8编码,并包含重音字符,如é,ö和å。
问题是我不控制将要使用该应用程序的页面上的字符集。
有些将使用UTF-8,但其他人将使用iso-8859-1 charset。这当然会使.json
文件中出现特殊字符。
如何使用javascript将特殊的UTF-8字符转换为iso-8859-1等效字符?
答案 0 :(得分:134)
实际上,一切都通常在内部存储为某种类型的Unicode,但不能进入。我假设您正在使用标志性的“åö”类型字符串,因为您使用的是ISO-8859作为字符编码。有一个技巧可以转换这些字符。用于编码和解码查询字符串的escape
和unescape
函数是针对ISO字符定义的,而执行相同操作的较新encodeURIComponent
和decodeURIComponent
是针对UTF8定义的字符。
escape
将扩展的ISO-8859-1字符(UTF代码点U + 0080-U + 00ff)编码为%xx
(两位十六进制),而它编码UTF代码点U + 0100及以上作为%uxxxx
(%u
后跟四位十六进制。)例如,escape("å") == "%E5"
和escape("あ") == "%u3042"
。
encodeURIComponent
将扩展字符百分比编码为UTF8字节序列。例如,encodeURIComponent("å") == "%C3%A5"
和encodeURIComponent("あ") == "%E3%81%82"
。
所以你可以这样做:
fixedstring = decodeURIComponent(escape(utfstring));
例如,编码错误的字符“å”变为“Ã¥”。该命令执行escape("Ã¥") == "%C3%A5"
,这是编码为单个字节的两个不正确的ISO字符。然后是decodeURIComponent("%C3%A5") == "å"
,其中两个百分比编码的字节被解释为UTF8序列。
如果你出于某种原因需要反向,那也是有效的:
utfstring = unescape(encodeURIComponent(originalstring));
有没有办法区分坏的UTF8字符串和ISO字符串?原来有。如果给定格式错误的编码序列,上面使用的decodeURIComponent函数将抛出错误。我们可以用它来检测我们的字符串是UTF8还是ISO。
var fixedstring;
try{
// If the string is UTF-8, this will work and not throw an error.
fixedstring=decodeURIComponent(escape(badstring));
}catch(e){
// If it isn't, an error will be thrown, and we can assume that we have an ISO string.
fixedstring=badstring;
}
答案 1 :(得分:7)
问题在于,一旦页面被提供,内容将采用content-type元标记中描述的编码。 “错误”编码中的内容已经出现乱码。
在提供页面之前,最好在服务器上执行此操作。或者据我所知: UTF-8端到端或死亡。
答案 2 :(得分:1)
在内部,Javascript字符串都是Unicode(实际上是UCS-2,UTF-16的子集)。
如果您是通过AJAX单独检索JSON文件,那么您只需确保使用正确的Content-Type和charset:Content-Type: application/json; charset="utf-8"
)提供JSON文件。如果你这样做,jQuery应该在你访问反序列化对象时已经正确地解释了它们。
您是否可以发布用于检索JSON对象的代码示例?
答案 3 :(得分:1)
由于关于如何从ISO-8859-1转换为UTF-8的question已关闭,因此我将在此处发布我的解决方案。
问题是当你尝试使用XMLHttpRequest获取任何东西时,如果XMLHttpRequest.responseType是" text"或者为空,XMLHttpRequest.response被转换为DOMString,并且这些东西被分解了。之后,几乎不可能可靠地使用该字符串。
现在,如果来自服务器的内容是ISO-8859-1,您必须强制响应类型为" Blob"然后将其转换为DOMSTring。例如:
var ajax = new XMLHttpRequest();
ajax.open('GET', url, true);
ajax.responseType = 'blob';
ajax.onreadystatechange = function(){
...
if(ajax.responseType === 'blob'){
// Convert the blob to a string
var reader = new window.FileReader();
reader.addEventListener('loadend', function() {
// For ISO-8859-1 there's no further conversion required
Promise.resolve(reader.result);
});
reader.readAsBinaryString(ajax.response);
}
}
似乎魔法发生在 readAsBinaryString 上,所以也许有人可以解释为什么会这样做。
答案 4 :(得分:0)
有些库可以用Javascript进行字符集转换。但是,如果您想要简单的东西,此函数可以完成您想要的事情:
function stringToBytes(text) {
const length = text.length;
const result = new Uint8Array(length);
for (let i = 0; i < length; i++) {
const code = text.charCodeAt(i);
const byte = code > 255 ? 32 : code;
result[i] = byte;
}
return result;
}
如果要将结果字节数组转换为Blob,则应执行以下操作:
const originalString = 'ååå';
const bytes = stringToBytes(originalString);
const blob = new Blob([bytes.buffer], { type: 'text/plain; charset=ISO-8859-1' });
现在,请记住,某些应用程序确实接受UTF-8编码,但是除非您预先加上BOM表字符,否则它们无法猜测编码,如here所述。
答案 5 :(得分:-1)
您应该在页面上方添加此行
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />