使用 JavaScript 解码 url 编码的 windows-1251 (cp1251) 字符串

Rom*_*ivo 6 javascript decode decoder cp1251 windows-1251

我遇到了一个问题,不幸的是,我没有找到正确的解决方案:我需要解码使用 windows-1251 (cp1251) 编码的 url-slice。

\n\n

我知道有这些方法-decodeURI()和decodeURIComponent(),但它们仅适用于UTF-8(据我所知)。我发现的解决方案使用已弃用的方法 escape() 和 unescape()。

\n\n

例如有一个序列:

\n\n

%EF%F0%EE%E3%F0%E0%EC%EC%E8%F0%EE%E2%E0%ED%E8%E5 (\xd0\xbf\xd1\x80\xd0\xbe\xd0\xb3\ xd1\x80\xd0\xb0\xd0\xbc\xd0\xbc\xd0\xb8\xd1\x80\xd0\xbe\xd0\xb2\xd0\xb0\xd0\xbd\xd0\xb8\xd0\xb5)

\n\n

方法decodeURI() 和decodeURIComponent() 将导致异常。

\n\n

将不胜感激的帮助。

\n

Nic*_*lay 5

据我所知,浏览器中没有对具有旧字符集的百分比编码方案的内置支持。你必须:

\n
    \n
  1. 找到代表 win-1251 八位字节的 %-escapes,
  2. \n
  3. 将 win-1251 八位字节解码为相应的字符 (JS String)
  4. \n
\n

下面是一种方法。对于#1,我假设只有 3 个字符的大写转义需要解码,并且字符串的其余部分已经是 ASCII,所以我只是用于此目的。inputStr.replace(/%([0-9A-Z]{2})/g, replacerFunction)

\n

对于实际解码,您需要从 win-1251 八位字节到 JS 字符的映射。在下面的示例中,我使用TextDecoder.decode() API构建映射 ,只是为了好玩(以防有人在尝试在 JS 中的不同字符集之间进行转换时找到此答案)。(注意:目前尚未得到普遍支持——只有 Gecko/Blink 支持)。

\n

还有https://github.com/mathiasbynens/windows-1251,我最初想用它来回答这个问题,但事实证明,手动构建解码图会更容易。

\n

\r\n
\r\n
var decodeMap = {};\nvar win1251 = new TextDecoder("windows-1251");\nfor (var i = 0x00; i <= 0xFF; i++) {\n  var hex = (i <= 0x0F ? "0" : "") +      // zero-padded\n            i.toString(16).toUpperCase();\n  decodeMap[hex] = win1251.decode(Uint8Array.from([i]));\n}\n// console.log(decodeMap);\n// {"10":"\\u0010", ... "40":"@","41":"A","42":"B", ... "C0":"\xd0\x90","C1":"\xd0\x91", ...\n\n\n// Decodes a windows-1251 encoded string, additionally\n// encoded as an ASCII string where each non-ASCII character of the original\n// windows-1251 string is encoded as %XY where XY (uppercase!) is a\n// hexadecimal representation of that character\'s code in windows-1251.\nfunction percentEncodedWin1251ToDOMString(str) {\n  return str.replace(/%([0-9A-F]{2})/g,\n    (match, hex) => decodeMap[hex]);\n}\n\nconsole.log(percentEncodedWin1251ToDOMString("%EF%F0%EE%E3%F0%E0%EC%EC%!%E8%F0%EE%E2%E0%ED%E8%FFa"))
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n