如何修复 JavaScript 中字符串的编码

问题描述 投票:0回答:1

我从另一个软件收到断线。我本来想在 JavaScript 中修复它的编码,但我觉得我错过了一些东西。

这里有一个断弦的例子:Détecté à lors à´´
预期输出为:Détecté àlors ôùi

我不知道用于向我发送字符串的编码。

我的想法是使用 TextDecoder API;将字符串转换为字节,然后以 UTF8 或 UTF16 重新编码。

这是我用来检测所使用的字符集的代码:

const str = 'Détecté àlors ôùi';
const str2 = 'Détecté àlors ôù';

const charsets = [
  'utf-8',
  "ibm866",
  "iso-8859-2",
  "iso-8859-3",
  "iso-8859-4",
  "iso-8859-5",
  "iso-8859-6",
  "iso-8859-7",
  "iso-8859-8",
  "iso-8859-8-i",
  "iso-8859-10",
  "iso-8859-13",
  "iso-8859-14",
  "iso-8859-15",
  "iso-8859-16",
  "koi8-r",
  "koi8-u",
  "macintosh",
  "windows-874",
  "windows-1250",
  "windows-1251",
  "windows-1252",
  "windows-1253",
  "windows-1254",
  "windows-1255",
  "windows-1256",
  "windows-1257",
  "windows-1258",
  "x-mac-cyrillic",
  "gbk",
  "gb18030",
  "hz-gb-2312",
  "big5",
  "euc-jp",
  "iso-2022-jp",
  "shift-jis",
  "euc-kr",
  "iso-2022-kr",
  "utf-16be",
  "utf-16le",
  "iso-2022-cn"
];

const encoder = new TextEncoder();
const view = encoder.encode(str2);

console.log('__________________')

charsets.forEach((charset) => {
  try {
    const decoder = new TextDecoder(charset);
    const fixedStr = decoder.decode(view, {
      fatal: false,
      ignoreBOM: true,
    });

    console.log(charset, fixedStr);
  } catch (e) {
    console.log(charset, 'invalid');
  }
})

(代码可以在这里测试:https://jsfiddle.net/tashebwj/

输出如下:

__________________
?editor_console=true:57 utf-8 Détecté àlors ôù
?editor_console=true:57 ibm866 D├Г┬йtect├Г┬й ├Г┬аlors ├Г┬┤├Г┬╣
?editor_console=true:57 iso-8859-2 DĂŠtectĂŠ Ă lors Ă´Ăš
?editor_console=true:57 iso-8859-3 D�Âİtect�Âİ � lors �´�Âı
?editor_console=true:57 iso-8859-4 DÊtectÊ àlors ôÚ
?editor_console=true:57 iso-8859-5 DУТЉtectУТЉ УТ lors УТДУТЙ
?editor_console=true:57 iso-8859-6 Dأآ�tectأآ� أآ lors أآ�أآ�
?editor_console=true:57 iso-8859-7 DΓΒ©tectΓΒ© ΓΒ lors ΓΒ΄ΓΒΉ
?editor_console=true:57 iso-8859-8 D��©tect��© �� lors ��´��¹
?editor_console=true:57 iso-8859-8-i D��©tect��© �� lors ��´��¹
?editor_console=true:57 iso-8859-10 DÃÂĐtectÃÂĐ Ã lors ÃÂīÃÂđ
?editor_console=true:57 iso-8859-13 DĆĀ©tectĆĀ© ĆĀ lors ĆĀ“ĆĀ¹
?editor_console=true:57 iso-8859-14 Détecté àlors ÃÂṀÃÂṗ
?editor_console=true:57 iso-8859-15 Détecté àlors ÃŽù
?editor_console=true:57 iso-8859-16 DĂ©tectĂ© Ă lors ĂÂŽĂÂč
?editor_console=true:57 koi8-r Dц┐б╘tectц┐б╘ ц┐б═lors ц┐б╢ц┐б╧
?editor_console=true:57 koi8-u Dц┐б╘tectц┐б╘ ц┐б═lors ц┐бЄц┐б╧
?editor_console=true:57 macintosh Détecté àlors ôù
?editor_console=true:57 windows-874 Dรยฉtectรยฉ รย lors รยดรยน
?editor_console=true:57 windows-1250 DĂ©tectĂ© Ă lors Ă´ĂÂą
?editor_console=true:57 windows-1251 DГѓВ©tectГѓВ© ГѓВ lors ГѓВґГѓВ№
?editor_console=true:57 windows-1252 Détecté àlors ôù
?editor_console=true:57 windows-1253 Détecté àlors ôù
?editor_console=true:57 windows-1254 Détecté àlors ôù
?editor_console=true:57 windows-1255 Dֳƒֲ©tectֳƒֲ© ֳƒֲ lors ֳƒֲ´ֳƒֲ¹
?editor_console=true:57 windows-1256 Dأƒآ©tectأƒآ© أƒآ lors أƒآ´أƒآ¹
?editor_console=true:57 windows-1257 DĆĀ©tectĆĀ© ĆĀ lors ĆĀ´ĆĀ¹
?editor_console=true:57 windows-1258 DĂƒÂ©tectĂƒÂ© ĂƒÂ lors ĂƒÂ´ĂƒÂ¹
?editor_console=true:57 x-mac-cyrillic D√Г¬©tect√Г¬© √Г¬†lors √Г¬і√Г¬є
?editor_console=true:57 gbk D脙漏tect脙漏 脙聽lors 脙麓脙鹿
?editor_console=true:57 gb18030 D脙漏tect脙漏 脙聽lors 脙麓脙鹿
?editor_console=true:57 hz-gb-2312 invalid
?editor_console=true:57 big5 D�穢tect�穢 ��饊ors �織�繒
?editor_console=true:57 euc-jp D�息tect�息 ��lors �卒�孫
?editor_console=true:57 iso-2022-jp D����tect���� ����lors ��������
?editor_console=true:57 shift-jis Dテδゥtectテδゥ テδ�lors テδエテδケ
?editor_console=true:57 euc-kr D횄짤tect횄짤 횄혻lors 횄쨈횄쨔
?editor_console=true:57 iso-2022-kr invalid
?editor_console=true:57 utf-16be 䓃菂ꥴ散瓃菂ꤠ쎃슠汯牳⃃菂듃菂�
?editor_console=true:57 utf-16le 썄슃璩捥썴슃₩菃ꃂ潬獲쌠슃쎴슃�
?editor_console=true:57 iso-2022-cn invalid

为什么这个方法不起作用?是否可以用这种方法或其他方法修复字符串?

javascript encoding charset textdecoder
1个回答
0
投票

运行:

> encodeURIComponent("Détecté àlors ôùi")  // str_expected
< 'D%C3%A9tect%C3%A9%20%C3%A0lors%20%C3%B4%C3%B9i'
> escape("Détecté àlors ôùi")
< 'D%E9tect%E9%20%E0lors%20%F4%F9i'

然后:

> escape("Détecté à lors ôù")  // str_actual
< 'D%C3%A9tect%C3%A9%20%C3%20lors%20%C3%B4%C3%B9'

我们可以看到两者几乎相同,因此可以得出结论,这个问题是因为

str_expected
中的UTF-8代码点:

D\xC3\xA9tect\xC3\xA9\x20\xC3\xA0lors\x20\xC3\xB4\xC3\xB9i

被误解为

str_actual
中的 Unicode 点(将每个字节转换为 UTF-16 代码点):

D\u00C3\u00A9tect\u00C3\u00A9\u0020\u00C3\u00A0lors\u0020\u00C3\u00B4\u00C3\u00B9i

而不是预期的解释(将 UTF-8 转换为 UTF-16):

D\u00E9tect\u00E9\u0020\u00E0lors\u0020\u00F4\u00F9i

要将 UTF8 字节字符串

str_actual
恢复为所需的 Unicode 字符串
str_expected
,请运行:

decodeURIComponent(escape(str_actual))

补充说明:

i
中缺少结尾
str_actual
可能只是因为您错过了选择它。而
\xC3\xA0lors
中的
str_expected
变为
\u00C3\u0020lors
中的
str_actual
可能是因为原始输出 \u00A0 中的
non-break space
(NBSP,
\u00C3\u00A0lors
) 已转换为 space (
\u0020
) 当复制为文本时。为了防止这种意外的转换,您可能必须将原始输出流直接重定向到文件,而不是手动选择并复制它。

© www.soinside.com 2019 - 2024. All rights reserved.