在Mac OS X中,文件系统的Unicode编码在Python中是否正确?

19

在 OS X 和 Python 中,我遇到了使用 Unicode 文件名的一些困难。我试图将文件名用作代码中稍后要用到的正则表达式的输入,但文件名中使用的编码似乎与 sys.getfilesystemencoding() 所告诉我的不同。以下是代码示例:

#!/usr/bin/env python
# coding=utf-8

import sys,os
print sys.getfilesystemencoding()

p = u'/temp/s/'
s = u'åäö'
print 's', [ord(c) for c in s], s
s2 = s.encode(sys.getfilesystemencoding())
print 's2', [ord(c) for c in s2], s2
os.mkdir(p+s)
for d in os.listdir(p):
  print 'dir', [ord(c) for c in d], d

它输出以下内容:

utf-8
s [229, 228, 246] åäö
s2 [195, 165, 195, 164, 195, 182] åäö
dir [97, 778, 97, 776, 111, 776] åäö

所以,文件系统编码为utf-8,但是当我使用该编码对我的文件名åäö进行编码时,它与使用相同字符串创建的目录名不同。我期望当我使用字符串åäö创建目录并读取其名称时,它应该使用与直接应用编码相同的代码。

如果我们看一下代码点97、778、97、776、111、776,它基本上是ASCII字符加上变音符号,例如o + ¨= ö,这使得它成为两个字符,而不是一个字符。我该如何避免这种差异?在Python中是否有一种编码方案与OS X的行为匹配,并且为什么getfilesystemencoding()没有给出正确的结果?

还是我搞砸了?


可以通过在文件名字符串上执行以下正则表达式来将它们转换为无变音符号的Unicode,从而解决这些特定字符的问题:m_aa = re.compile(ur"a\u0308",re.I), m_ae = re.compile(ur"a\u030a",re.I), m_oe = re.compile(ur"o\u0308",re.I) - RipperDoc
2个回答

27

在使用node.js时遇到了问题,npm包unorm提供了非常好的接口来解决这个问题。 - mmilleruva

23

getfilesystemencoding() 提供了正确的响应(即编码),但它并没有告诉你unicode normalisation form

特别是,HFS+ 文件系统使用 UTF-8 编码,并且接近于 "D" 的规范化形式(需要将组合字符如 ö 分解为 )。 HFS+ 还与 Unicode 版本 3.2 中存在的规范化形式相关联,详见苹果公司的documentation for the HFS+ format

Python 的unicodedata.normalize方法在不同形式之间进行转换,如果在调用前加上ucd_3_2_0对象,则可以将其限制为 Unicode 版本 3.2:

filename = unicodedata.ucd_3_2_0.normalize('NFC', unicode(filename, 'utf-8')).encode('utf-8')

谢谢,很棒的答案,希望我能够给两个答案都点赞并接受! - RipperDoc
2
实际上,它并不完全是NFD,但很接近。 - tchrist
如果HFS+以分解形式存储文件名,那么您是否会使用normalise('NFD'...)来匹配HFS+编码? - Craig McQueen

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