Javascript:比较两个具有实际不同编码的字符串

标签 javascript encoding string-comparison

我正在用 Javascript 比较两个可能不同编码的文件名,希望找到匹配项:

分析

当比较 JavaScript 控制台中的日志输出时,这些文件名看起来完全相同:

15 - Beschänkt und gsägnet - PLAYBACKVERSION.mp3
15 - Beschänkt und gsägnet - PLAYBACKVERSION.mp3

注意德语变音符号。

现在,当我将这些字符串复制并粘贴到 Notepad++ 并启用十六进制编辑器时,它看起来像这样:

The above text in hex

  • 在第一种情况下,A-Umlaut 使用 3(三) 字节进行编码
  • 在第二种情况下,A-Umlaut 仅使用 2(两个)字节进行编码。

问题

如何安全地比较这两个字符串。 Javascript 中是否有通用的“unencode”方法可以处理这些实例?或者我应该/必须猜测每种编码,然后显式比较吗?

注意

最佳答案

这里发生了什么?

如果 JavaScript 中有一个 String,它就是一个 Unicode 代码点序列。某些组件已经将 ZIP 或 plist 中表示这些字符串的字节解码为代码点序列。

也就是说,这个问题并不完全是关于编码,而是关于 Unicode 分解和规范化形式。

可以在 Unicode 中以(至少)两种不同的方式对 ä 进行编码(由于有用的输出,下面的示例在 Python 中)。

>>> "ä".encode("UTF-8")
b'\xc3\xa4'  # two bytes
>>> [ord(c) for c in "ä"]
[228]
>>> [unicodedata.name(c) for c in "ä"]
['LATIN SMALL LETTER A WITH DIAERESIS']

或者采用 NFKD 规范化形式,采用 UTF-8 格式的两个代码点和三个字节。

>>> unicodedata.normalize("NFKD", "ä").encode("UTF-8")
b'a\xcc\x88'  # three bytes
>>> [ord(c) for c in unicodedata.normalize("NFKD", "ä")]
[97, 776]  # two codepoints
>>> [unicodedata.name(c) for c in unicodedata.normalize("NFKD", "ä")]
['LATIN SMALL LETTER A', 'COMBINING DIAERESIS']

回答

长话短说,在 JavaScript 中,您需要调用 String#normalize()在尝试常规比较之前确保字符串处于相同的规范化形式。

$ node
Welcome to Node.js v16.6.1.
Type ".help" for more information.
> var a = '15 - Beschänkt und gsägnet - PLAYBACKVERSION.mp3';
undefined
> var b = '15 - Beschänkt und gsägnet - PLAYBACKVERSION.mp3';
undefined
> a.length
50
> b.length
48
> a === b
false
> a.normalize() === b.normalize()
true
>

关于Javascript:比较两个具有实际不同编码的字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69177720/

相关文章:

javascript - AngularJS : Scope inaccessible in directive after minification

javascript - 查找上一个按钮的 ID

php - 在 Postgres 中存储 Zip 文件

Java:检查字符串是否在单词列表中的最有效方法

java - android中的密码验证确认

javascript - 如何将 javascript 创建的 blob 传递给 JSF bean

javascript - 过滤后 SlickGrid 行 ID 发生变化

sql - Powershell XML编码

c# - 类 Base64 字符串转换,到更小的字符集

python - 检查字符串是否以 XXXX 开头