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

IT技术 javascript jquery character-encoding
2021-02-08 09:01:09

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

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

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

有些将使用 UTF-8,但其他将使用 iso-8859-1 字符集。这当然会使.json文件中的特殊字符乱码

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

6个回答

实际上,所有内容通常都在内部存储为某种 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;
}
我已经在我自己的问题的答案中引用了您的答案:stackoverflow.com/questions/18847191/...
2021-03-17 09:01:09
@nitro:javascript 是否将每个 utf-8 字符视为 ISO 拉丁字符?
2021-03-21 09:01:09
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"我希望能解决任何问题。
2021-03-31 09:01:09
@nitro2k01:您的建议出现错误: Uncaught URIError: URI malformed
2021-04-10 09:01:09
2021-04-12 09:01:09

问题在于,一旦提供了页面,内容将采用内容类型元标记中描述的编码。“错误”编码的内容已经是乱码。

您最好在提供页面之前在服务器上执行此操作。或者正如我所知:UTF-8 end-to-end or die

这不能回答问题!
2021-03-19 09:01:09
虽然我的页眉已经说它是 utf-8,但我不得不将它转换为 ISO 拉丁语以进一步加密。stackoverflow.com/questions/18786025/...
2021-04-05 09:01:09

由于问题如何从ISO-8859-1转换为UTF-8,因为这一次我要在这里发布我的解决方案的关闭。

问题是当您尝试使用 XMLHttpRequest 获取任何内容时,如果 XMLHttpRequest.responseType 为“文本”或为空,则 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 上,所以也许有人可以解释一下为什么会这样。

在内部,Javascript 字符串都是 Unicode(实际上是 UCS-2,UTF-16 的子集)。

如果您通过 AJAX 单独检索 JSON 文件,那么您只需要确保使用正确的 Content-Type 和字符集提供 JSON 文件:) Content-Type: application/json; charset="utf-8"如果你这样做了,当你访问反序列化对象时,jQuery 应该已经正确地解释了它们。

您能否发布一个用于检索 JSON 对象的代码示例?

这是无关紧要的,既设置内容类型也设置字符集:jQuery 以完全相同的方式解释所提供的 json。可能是因为规范(ietf.org/rfc/rfc4627.txt)说JSON text SHALL be encoded in Unicode. The default encoding is UTF-8因此,将标头设置为Content-Type: application/json; charset="iso-8859-1"来自以 iso-8859-1 编码的文件的变量的 json 编码文本,并通过 ajax 将其发送到 iso-8859-1 编码的 html 页面会产生与未指定任何内容相同的结果:字符串是浏览器解释为NULL
2021-03-13 09:01:09

有一些库可以在 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字符,他们无法猜测的编码,解释在这里

您能否建议用于在 Javascript 中进行字符集转换的库选项?
2021-03-26 09:01:09