JavaScript 中的 Unicode 和 URI 编码、解码和转义

Bjo*_*orn 2 javascript unicode encode urlencode utf-8

如果您查看此处的此表,您会发现它有一个 Unicode 字符的转义序列列表,但实际上对我来说不起作用。

\n\n

例如,对于“%96”,它应该是 \xe2\x80\x93,我在尝试解码时收到错误:

\n\n
decodeURIComponent("%96");\nURIError: URI malformed\n
Run Code Online (Sandbox Code Playgroud)\n\n

如果我尝试编码“\xe2\x80\x93”,我实际上得到:

\n\n
encodeURIComponent("\xe2\x80\x93");\n"%E2%80%93"\n
Run Code Online (Sandbox Code Playgroud)\n\n

我在互联网上搜索,看到了这个页面,其中提到分别使用 escape 和 unescape 与decodeURIComponent和encodeURIComponent。这似乎没有帮助,因为无论我尝试什么,%96 都不会显示为“\xe2\x80\x93”,这当然是行不通的:

\n\n
decodeURIComponent(escape("%96));\n"%96"\n
Run Code Online (Sandbox Code Playgroud)\n\n

不是很有帮助。

\n\n

如何使用 JavaScript 将“%96”变为“\xe2\x80\x93”(无需为我可能遇到的每个可能的 unicode 字符硬编码映射)?

\n

Gar*_*son 6

URI 中的序列%XX编码一个“八位字节”,即一个八位字节。这就提出了一个问题:解码后的字节指的是哪个 Unicode 字符。如果我没记错的话,在旧版本的 URI 规范中,并没有很好地定义假定的字符集。在 URI 规范的更高版本中,建议使用 UTF-8 作为默认编码字符集。也就是说,要解码字节序列,您需要解码每个%XX序列,然后使用 UTF-8 字符集将结果字节转换为字符串。

这解释了为什么%96无法解码。十六进制 0x96 值不是有效的 UTF-8 序列。由于它超出了 ASCII,因此在它之前需要一个特殊的修饰符字节来指示扩展字符。(有关更多详细信息,请参阅 UTF-8 规范。)JavaScriptencodeURIComponent()decodeURIComponent()方法都假定 UTF-8(正如它们应该的那样),因此我不希望%96能够正确解码。

您引用的字符是 U+2013,一个破折号。您引用的页面到底是如何从十六进制 0x96(十进制 150)获得一个破折号的?他们显然没有假设 UTF-8 编码,这是标准。他们没有假设 ASCII,因为 ASCII 不包含该字符。他们甚至没有假设ISO-8859-1,这是一种每个字符使用一个字节的标准编码。事实证明,他们采用了特殊的Windows 1252代码页。也就是说,您尝试解码的 URI 假定用户使用的是 Windows 计算机,更糟糕的是,用户使用的是英语(或其他几种西方语言之一)的 Windows 计算机。

简而言之,您使用的表很糟糕。它已经过时,并且假设用户使用的是英语 Windows 系统。对非 ASCII 值进行编码的最新且正确的方法是将其转换为 UTF-8,然后使用%XX. 这就是为什么%E2%80%93当你尝试对字符进行编码时会得到这样的结果,这就是所decodeURIComponent()期望的。您使用的 URI 编码不正确。如果您没有其他选择,您可以猜测 URI 使用的是 Windows 1252,自行转换字节,然后使用 Windows 1252 表来找出预期的 Unicode 值。但这是有风险的——您如何知道哪个 URI 使用哪个表?这就是为什么每个人都选择 UTF-8。如果可能,请告诉向您提供这些 URI 的人正确编码。