3

(在 StackOverflow 上已经提出了类似的问题,但不完全是这个。最近的可能是“ javascript how to convert unicode string to ascii ”,其中已经有“this has to be a dup[licate]”的注释。我已经阅读了一些类似的帖子,但他们没有回答我的具体问题。我查看了非常好的W3Schools网站,也搜索了它,但也没有找到答案。所以这里的任何提示都会非常重要赞赏。)


我有一个字节数组被传递给一段 JavaScript。在 JavaScript 中,数据以字符串形式到达。我不知道传输机制,因为它来自第 3 方应用程序。我什至不知道字符串是“宽”还是“窄”。

在我的 JavaScript 中,我有一些类似b = str.charCodeAt(pos);.

我的问题是 0x86 = 134 之类的字节值以字符 0x2020 = 8224 的形式出现。这似乎是因为我的原始字节被解释为 Latin-1(可能)“匕首”字符,然后被翻译成等效的 Unicode 代码点。(问题可能是也可能不是 JavaScript 的“错误”。)其他值也会出现类似的问题,尽管范围 0x00..0x7F 和 0xA0..0xFF 似乎没问题,但 0x80..0x9F 中的大多数值都会受到影响,在每种情况下的值似乎都是原始 Latin-1 的 Unicode。

另一个观察结果是,如果长度以字节为单位,那么字符串的长度就是我对窄字符串的期望。(另一方面,如果长度返回一个抽象字符的值,这并不能告诉我任何事情。)

那么,在 JavaScript 中,有没有办法获取字符串中的“原始”字节,或者直接获取 Latin-1 或 ASCII 字符代码,或者在字符编码之间进行转换,或者定义默认编码?

我可以编写自己的映射,但我不想这样做。我希望这就是我最终会做的事情,但那感觉就像一个杂物。

我还在研究调用应用程序中是否有什么可以调整的(因为它可能将数据作为宽字符串传递,尽管我对此表示怀疑)。

不过,无论哪种方式,我都会对是否有简单的 JavaScript 解决方案感兴趣,或者想了解为什么没有。

(如果传入的数据是字符数据,那么自动处理 Unicode 会很棒。但它不是,它只是一个二进制数据流。)

谢谢。

4

2 回答 2

6

字符串中没有原始字节之类的东西。EcmaScript 规范将字符串定义为 UTF-16 代码单元序列。这是任何解释器所遇到的最细粒度的表示。

在浏览器上没有编码库。如果您尝试将字节数组表示为字符串并想要对其重新编码,则必须自己动手。

charCodeAt如果您的字符串恰好是有效的 ASCII,那么您可以使用该方法获取代码单元的数值。

"\n".charCodeAt(0) === 10
于 2011-01-29T01:31:21.330 回答
3

从 Javascript (Ecmascript) 规范开始:http: //www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf。是说:

8.4 字符串类型 字符串类型是零个或多个 16 位无符号整数值(“元素”)的所有有限有序序列的集合。String 类型通常用于表示正在运行的 ECMAScript 程序中的文本数据,在这种情况下,String 中的每个元素都被视为一个代码单元值(参见第 6 条)。每个元素都被视为在序列中占据一个位置。这些位置用非负整数索引。第一个元素(如果有)在位置 0,下一个元素(如果有)在位置 1,依此类推。字符串的长度是其中元素的数量(即 16 位值)。空字符串的长度为零,因此不包含任何元素。

当一个字符串包含实际的文本数据时,每个元素都被认为是一个 UTF-16 代码单元。无论这是否是字符串的实际存储格式,字符串中的字符都按其初始代码单元元素位置编号,就好像它们使用 UTF-16 表示一样。对字符串的所有操作(除非另有说明)都将它们视为未区分的 16 位无符号整数序列;他们不确保生成的字符串是规范化的形式,也不确保语言敏感的结果。

注意此设计背后的基本原理是使字符串的实现尽可能简单和高性能。目的是从外部进入执行环境的文本数据(例如,用户输入、从文件读取或通过网络接收的文本等)在运行程序看到之前转换为 Unicode 规范化形式 C。通常这会在传入文本从其原始字符编码转换为 Unicode 的同时发生(并且不会产生额外的开销)。由于建议 ECMAScript 源代码采用规范化形式 C,因此只要字符串不包含任何 Unicode 转义序列,就可以保证对字符串文字进行规范化(如果保证对源文本进行规范化)。

charCodeAt(p给你的是字符串中索引p)处字符的 UTF-16 值(一个 16 位数字)。由于 UTF-16 直接代表 Unicode 的基本多语言平面(即代码点–和– ,您的 Latin-1 字符应该是您期望的值。U+0000U+D7FFU+E000U+FFFF

他们不是向我表明您对入站第三个八位字节流有编码问题的事实 - 如果正在完成到 UTF-16 的转换并且入站八位字节流的编码错误,您会得到奇怪的结果。

也许它被视为普通 ASCII,而实际上它是 UTF-8(反之亦然)。UTF-8 将 0x7F 以上的代码点表示为 2、3 或 4 八位字节的“二合字母”。

于 2011-01-29T01:39:42.800 回答