Python UTF8 编码

标签 python encoding utf-8

我查看了有关 Python 和编码的其他问题,但还没有找到解决问题的方法。这里是:

我有一个小脚本,它试图比较 2 个文件列表:

  • 文本文件中给出的列表,应该以 UTF8 编码(至少 Notepad++ 会这样检测)。
  • 我这样构建的目录中的列表:
    local = [f.encode('utf-8') for f in listdir(dir) ]
    

  • 但是,对于某些字符,我没有得到相同的表示:在 HEX 编辑器中查看时,我发现在 1 中,字符 é65 cc 给出而在 2 中,它由 c3 a9 给出...

    我想要的是让它们具有相同的编码,无论它是什么。

    最佳答案

    您的第一个序列不完整 - cc是两字节 UTF-8 序列的前缀。最有可能的是,完整的序列是 65 cc 81 ,这确实是字符 e (0x65) 后跟 COMBINING ACUTE ACCENT (0x301,在 UTF-8 中表示为 cc 81)。

    另一个序列是预先组合的 LATIN SMALL LETTER E WITH ACUTE字符(0xe9,在 UTF-8 中表示为 c3 a9)。您会在链接页面中注意到它的分解正是第一个序列。

    Unicode 规范化

    现在,在 Unicode 中有许多不同序列的实例在图形和/或语义上是相同的,虽然将 UTF-8 流视为不透明的二进制序列通常是个好主意,但如果你想这样做,这会带来问题搜索或索引 - 寻找一个序列不会匹配另一个,即使它们在图形和语义上是相同的。因此,Unicode 定义了 four types of normalization ,可用于“展平”这种差异并从组合形式和分解形式中获得相同的代码点。例如,在这种情况下,NFC 和 NFKC 规范化形式将为您的两个序列提供 0xe9 代码点,而 NFD 和 NFKD 将提供 0x65 0x301 分解形式。

    要在 Python 中执行此操作,您首先需要 decode你的 UTF-8 str反对unicode对象,然后使用 unicodedata.normalize方法。

    重要提示 :除非您正在实现“智能”索引/搜索,否则不要规范化,并且仅将规范化数据用于此目的 - 即索引和搜索规范化,但将原始表单存储/提供给用户。规范化是一种有损操作(某些形式尤其如此),盲目地将其应用于用户数据就像用大锤进入陶器店一样。

    文件路径

    好的,这通常是关于 Unicode 的。谈论文件系统路径既简单又复杂。

    原则上,Windows 和 Linux 上几乎所有常见的文件系统都将路径视为 。不透明 character1 序列(以目录分隔符和可能的 NUL 字符为模),没有应用特定的规范化形式2。因此,在给定目录中,您可以拥有两个看起来相同但实际上不同的文件名:

    two files named é in terminal

    因此,当按照原则处理文件路径时,您永远不应该规范化——同样,文件路径是一个不透明的代码点序列(实际上,在 Linux 上是一个不透明的字节序列),不应该被弄乱。

    但是,如果您收到并且您必须处理的列表被不同地标准化(这可能意味着它已经通过一个损坏的软件传递,该软件“有用地”标准化组合/分解的序列,或者名称是手动输入的) 你必须执行一些标准化匹配。

    如果我要处理类似的(根据定义打破)场景,我会做这样的事情:

  • 首先尝试完全匹配;
  • 如果失败,尝试将规范化的文件名与 set 匹配。包含目录的规范化内容;请注意,如果多个原始名称映射到同一个规范化名称并且您不完全匹配它,您将无法知道哪个是“正确的”。


  • 脚注
  • Linux 原生文件系统都使用基于 8 位字节的路径——它们可能采用任何编码,内核不在乎,尽管最近的系统通常碰巧使用 UTF-8; Windows 原生文件系统将改为使用 16 位基于字的路径,这些路径名义上包含 UTF-16(最初是 UCS-2)值。
  • 在 Windows 上,API 级别有点复杂,因为执行代码页转换的整个 ANSI API 困惑,Win32 路径的不区分大小写匹配增加了一层复杂性,但在内核和文件系统级别,它都是不透明的 2 -字节WCHAR字符串。
  • 关于Python UTF8 编码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44897977/

    相关文章:

    python - 将转置分组 pandas 数据帧输出到 CSV

    encoding - 字符编码的最佳资源

    ios - String 仅返回 splitBy 之后的数字

    c - gcc 和警告中的希腊字符

    mysql - 使用 phpmyadmin 导入 CSV utf8

    asp-classic - 经典 ASP 文本替换和 UTF-8 编码

    php - JSON 类无法处理阿拉伯语单词

    python - 在Python中,是否可以迭代每个线程存储在线程局部中的值?

    python - 多个标签作为 ML 的训练数据

    python - 从脚本设置 Scrapy start_urls