Mac OS X中文件系统的Unicode编码在Python中不正确



在OSX和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,但当我使用它对文件名åäö进行编码时,它将与使用相同字符串创建目录名不同。我希望当我使用字符串åäö创建一个dir,并读取它的名称时,它应该使用与我直接应用编码相同的代码。

如果我们看代码点9777897776111776,它基本上是添加了变音符号的ASCII字符,例如o+¨=ö,这使它成为两个字符,而不是一个字符。我如何避免这种差异,Python中是否有一种编码方案与OSX的这种行为相匹配,为什么getfilesystemencoding()不能给我正确的结果?

还是我搞砸了?

MacOSX使用一种特殊的分解UTF-8来存储文件名。如果您需要读取文件名并将其写入"正常"UTF-8文件,则必须对其进行规范化:

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

从这里:https://web.archive.org/web/20120423075412/http://boodebr.org/main/python/all-关于python和unicode

getfilesystemencoding()会给您正确的响应(编码),但它不会告诉您unicode规范化形式。

特别是,HFS+文件系统使用UTF-8编码和接近"D"的规范化形式(这需要像ö这样的组合字符分解为)。HFS+也与规范化形式联系在一起,因为它存在于Unicode 3.2版中,苹果的HFS+格式文档中对此进行了详细说明。

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')

最新更新