如何在JavaScript中从字符串获取ASCII码?

3

(类似的问题已经在StackOverflow上提出过,但并不完全相同。最接近的可能是 "javascript how to convert unicode string to ascii",其中已经有了“这必须是一个重复”的备注。我读了一些类似的帖子,但它们没有回答我的具体问题。我在非常好的W3Schools网站上查找过,并且也进行了谷歌搜索,但也没有找到答案。所以这里任何提示都将不胜感激。)


我有一个字节数组传递给JavaScript代码。在JavaScript中,数据按字符串形式到达。由于这是从第三方应用程序传输的,我不知道传输机制,也不知道该字符串是“宽”还是“窄”。
在我的JavaScript代码中,我有一些类似b = str.charCodeAt(pos);的代码。
我的问题是,如0x86 = 134这样的字节值以字符0x2020 = 8224的形式传递,原因似乎是我的原始字节被解释为拉丁-1(可能是)'dagger'字符,然后被翻译成等效的Unicode代码点。(问题可能或可能不是JavaScript的“错”。)其他值也存在类似的问题,尽管范围为0x00..0x7F和0xA0..0xFF的大多数值都没有问题,但大多数值从0x80..0x9F受影响,在每种情况下,该值似乎是原始拉丁-1的Unicode。
另一个观察结果是,如果长度以字节为单位测量,则字符串的长度符合窄字符串的预期长度。(另一方面,如果长度返回抽象字符值,则这对我来说没有意义。)
在JavaScript中,是否有一种方法可以获取字符串中的“原始”字节,直接获取Latin-1或ASCII字符代码,或者在字符编码之间进行转换或定义默认编码?
我可以编写自己的映射,但我宁愿不这样做。我希望这不是解决问题的唯一方法。
我还在研究调用应用程序中是否有任何可调整的内容(因为它可能会将数据作为宽字符串传递,尽管我怀疑)。
无论哪种方式,我都对是否存在简单的JavaScript解决方案感兴趣,或者理解为什么不存在这样的解决方案。
(如果输入数据是字符数据,那么自动处理Unicode将非常好。但它不是,它只是一个二进制数据流。)
谢谢。

Latin-1字符集中没有DAGGER字符。您可能指的是Windows-1252。 - dan04
2个回答

6

在字符串中不存在原始字节。ECMAScript规范将字符串定义为UTF-16代码单元序列。这是任何解释器所公开的最细粒度的表示。

在浏览器中没有编码库。如果您想要将字节数组表示为字符串并重新编码,则必须自己编写。

如果您的字符串已经是有效的ASCII,则可以使用charCodeAt方法获取代码单元的数值。

"\n".charCodeAt(0) === 10

我接受了关于“EcmaScript规范将字符串定义为UTF-16代码单元序列”的片段的答案。目前我已经自己编写了一个哈希函数,以后可能会找到更好的解决方案。谢谢。 - Rhubbarb

3
起步先看JavaScript(Ecmascript)规范:http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf。它说:

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

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

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

charCodeAt(p)提供的是字符串中索引为p的字符的UTF-16值(一个16位数字)。由于UTF-16直接表示Unicode的基本多语言平面(即代码点U+0000U+D7FFU+E000U+FFFF),所以您的Latin-1字符应该是您期望的值。
他们没有正确显示,这表明您在处理输入的第三个八位字节流时存在编码问题。如果将其转换为UTF-16并且获取了错误的入站八位字节流编码,则会得到奇怪的结果。
也许它被视为普通ASCII,而实际上它是UTF-8(或反之亦然)。 UTF-8将代码点0x7F以上表示为2、3或4个八位字节的“双字”。

谢谢提供信息。虽然编码没有问题,但是这些值作为Unicode值是完全有意义的:这些值被合理地翻译了;我只是不想让它们被翻译。无论如何,你提供的信息很有帮助。 - Rhubbarb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接