如何使用javascript将特殊的UTF-8字符转换为iso-8859-1等效字符?

时间:2011-03-22 19:13:07

标签: javascript jquery character-encoding

我正在创建一个javascript应用程序,它使用jquery检索.json个文件,并将数据注入其嵌入的网页中。

.json文件采用UTF-8编码,并包含重音字符,如é,ö和å。

问题是我不控制将要使用该应用程序的页面上的字符集。

有些将使用UTF-8,但其他人将使用iso-8859-1 charset。这当然会使.json文件中出现特殊字符。

如何使用javascript将特殊的UTF-8字符转换为iso-8859-1等效字符?

6 个答案:

答案 0 :(得分:134)

实际上,一切都通常在内部存储为某种类型的Unicode,但不能进入。我假设您正在使用标志性的“åö”类型字符串,因为您使用的是ISO-8859作为字符编码。有一个技巧可以转换这些字符。用于编码和解码查询字符串的escapeunescape函数是针对ISO字符定义的,而执行相同操作的较新encodeURIComponentdecodeURIComponent是针对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" />