当前位置: 首页 > 知识库问答 >
问题:

如何使用Unicode::规范化以创建最兼容的Windows-1252编码字符串?

裴宏壮
2023-03-14

我在Perl中有一个旧版应用程序,最有可能处理以UTF-8编码的XML,并且需要将该XML的某些数据存储在某个数据库中,该数据库出于历史原因使用Windows-1252。是的,此设置不能支持Unicode标准的所有可能字符,但在实践中,我不需要这样做,并且可以尝试合理的兼容性。

当前的具体问题是一个包含LATIN SMALL LETTER U,COMBINING DIAERESISU 0075 U 0308>)的文件,这使得Perl将Unicode字符串的现有编码中断为

“\x{0308}”未映射到cp1252

我使用Unicode::Normalize::NFKC解决了这个问题,它创建了字符U00FCü>),它完美地映射到 。当然,这会导致其他一些问题,例如,在字符 VULGAR FRACTION ONE HALF½ >)的情况下,因为 会创建 ion="" slash、digit="" two<="" ode=""> ( 1/2U 0031 U 2044 U 0032

“\x{2044}”未映射到cp1252

根据规范化规则,这对于NFKC来说非常合适。我之所以使用它,是因为我认为它会给我带来最兼容的结果,但那是错误的。相反,使用NFC修复了这两个问题,因为在这种情况下,这两个字符都提供了与windows-1252

这种方法对于通常可获得与< code>windows-1252兼容的标准化的字符来说会产生额外的问题,只是不同于< code>NFC。一个例子是< code >拉丁文小写连字FI (< code > FI ,< code>U FB01)。根据其规范化规则,在< code>NFC之后的表示与< code>windows-1252不兼容,而这次使用< code>NFKC会导致两个字符与< code>windows-1252兼容:< code > fi (< code > U 0066 U 0069 )。

我目前的方法是简单地尝试按原样编码为Windows-1252,如果失败,我正在使用NFC并重试,如果失败,我使用NFKC并重试,如果失败,我现在放弃。这适用于我目前正在处理的情况,但如果上面示例的所有三个字符同时存在于字符串中,则显然会失败。然后总是有一个字符导致Windows-1252不兼容的输出,无论NFCNFKC的顺序如何。唯一的问题是哪个字符在何时中断。

但重要的是,每个字符本身都可以规范化为与windows-1252兼容的字符。只是似乎没有一次性解决方案。

那么,我是否遗漏了一些API,它已经以最向后兼容的方式进行了转换?

如果没有,我需要自己实现什么方法来支持一个字符串中的所有上述字符?

听起来我需要逐个处理每个字符串的Unicode-字符,用与windows-1252最兼容的字符单独规范化,然后再次连接结果。是否有一些增量Unicode-字符解析器可以处理字符和其他东西的组合?一个简单的基于Unicode-字符的正则表达式已经处理了这个问题吗?

Unicode::Normalize提供了额外的函数来处理部分字符串等,但我必须承认,我目前还没有完全理解它们的目的。示例也侧重于连接,但根据我的理解,我首先需要一些解析,以便能够以不同的方式规范化单个字符。

共有2个答案

鄢博简
2023-03-14

既然似乎可以根据需要转换单个字符(转换为cp-1252编码),那么一种方法是,一旦一个单词没有通过这个过程,就像建议的那样,逐个字符地处理。

Perl的regex中的< code>\X匹配一个逻辑Unicode字符,一个扩展的字素簇,作为单个码点或序列。因此,如果您确实可以将所有单个(逻辑)字符转换成所需的编码,那么使用

while ($word =~ /(\X)/g) { ... }

您可以访问逻辑字符并将您的工作过程应用于每个字符。

如果无法处理可能出现的所有逻辑字符,请使用特定字符属性拼凑出 \X 的等效项,以便通过组合标记等(如 /(())等进行更精细的粒度处理\p{Mn}?)/,或 \p{Nonspacing_Mark})。完整,宏伟的列表是用佩鲁尼普勒斯。

葛霄
2023-03-14

我不认为你错过了一个API,因为一个尽力而为的方法相当复杂。我会尝试如下方法:

  • 使用NFC进行规范化。这结合了分解的序列,例如拉丁小写字母U,组合DIAERESIS。
  • 使用正则表达式/\PM/g提取所有未组合标记的代码点。这会丢弃NFC转换后剩余的所有组合标记,这些标记无论如何都无法转换为Windows-1252。然后对于每个代码点:
    • 如果代码点可以转换为Windows-1252,请这样做。
    • 否则尝试使用NFKC规范化代码点。如果NFKC映射与输入不同,请在生成的字符串上递归地应用所有步骤。这处理连接之类的事情。
    • 作为奖励:如果代码点在NFKC下是不变的,请转换为NFD并尝试将结果的第一个代码点转换为Windows-1252。这将等字符转换为G。
    • 否则忽略字符。

    当然,还有其他方法可以将不受支持的字符转换为看起来相似的字符,但它们需要手动创建映射。

 类似资料:
  • 问题内容: 在Python中,是否存在标准化unicode字符串的标准方法,以使其仅包含可用于表示它的最简单的unicode实体? 我的意思是,一些东西,想翻译的顺序来? 查看问题出在哪里: 但现在: 当然,我可以遍历所有字符并进行手动替换等,但是效率不高,我敢肯定我会错过一半的特殊情况,并且会犯错误。 问题答案: 该模块提供一个功能,您要标准化为NFC格式: NFC或“普通形式组合”返回组成的字

  • 我有一个缓冲区与字符编码在Windows 1252。然而,当我用适当的编码创建一个新的字符串时,而不是预期的结果,我经常会得到询问标记,例如。 因此,系统应在其上方显示带“^”的“u”字符。而是显示“?”。 任何想法?

  • 我正在利用设置。。。方法(例如SetupGetLineText)从inf文件中读取一些内容(我需要它,对通用ini解析器不感兴趣)。这些方法使用Windows-1252编码,我需要将其转换为Unicode。我使用一个字符串得到了这个结果,比如这个(输入类型为string): 编码。UTF8.编码。编码(1252).GetBytes(输入)); 即使这很好,您也可以立即从SetupGetLineTe

  • Windows中使用的默认unicode字符编码是什么?特别是在Windows编程中(Win32和WinRT)。当我在WinAPI中编程时,“char”映射到1字节字符存储,“wchar_t”映射到2字节字符存储。如果UTF-16用4个字节编码所有超过65536的字符,那么Windows如何将这些字符映射为“wchar_t”数据类型?我知道我的问题不够清楚,但我希望你能理解我的一些担忧。非常感谢!

  • 我需要将上传的文件名转换为未知编码的Windows 1252,同时保持UTF-8兼容性。 当我将这些文件传递给控制器(我对其没有任何影响)时,这些文件必须经过Windows-1252编码。然后,该控制器再次生成通过MySQL存储到数据库中的有效文件(名称)列表-因此我需要UTF-8兼容性。传递给控制器的文件名和写入数据库的文件名必须匹配。到目前为止还不错。 在一些罕见的情况下,当转换为“Windo

  • 我很困惑,为什么我不应该用UTF-8编码unicode文本进行比较,而其他文本(要比较)已经用UTF-8编码了? 但是,当我用UTF-8编码并尝试将其与进行比较时,结果是。代码是 所以我的疑问是,当两个字符串都是相同的,并且都是用UTF-8编码的时候,为什么上面的比较失败了?结果应该为。 但是,在第一种情况下,当比较不同的编码字符串时--一种是UTF-16(Java默认的字符串编码方式),另一种是