作者apua (Apua)
看板Python
标题[闲聊] 在 M$ 环境下读档
时间Thu Feb 27 16:35:04 2014
分享一个这两天遇到焦头烂额的问题
在 M$ Windows 上档名有时会碰到表意文字补充区[1]的字
他不列在 CP950 (Big5) 里, 可是档名确实存在该字
如果用 Python os.listdir() 或 Popen('dir',...) 读出来的话,
会自动转为 CP950 的同义字 (也就是说该字会被偷偷改成别的字)
.. [1]:
http://en.wikipedia.org/wiki/CJK_Compatibility_Ideographs_Supplement
这里举一个表意文字的例子::
>>> s = u'\u57fa\uf90a'
>>> print s
基金
>>> s.encode('CP950')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'cp950' codec can't encode character u'\uf90a' in
position 1: illegal multibyte sequence
从 print out 的结果看来, 这个 "金" 字没有异常
但事实上他根本不是一般的 "金" 字 (正常的 "金" 理应为 u'\u91d1')
在 M$ Windows 上, 如果复制 ``print s`` 的结果存成一个档名, 将会遇到以下状况::
>>> import os; A = os.listdir('.'); A
['\xb0\xf2\xaa\xf7']
>>> A[-1].decode('CP950')
u'\u57fa\u91d1'
>>> open(A[-1])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IOError: [Errno 2] No such file or directory: '\xb0\xf2\xaa\xf7'
显然原因是 "金" 那个字从根本上被改掉了, 所以档案找不到
然後? 然後我们设计的程式就爆炸了.....(上百个档案都有这个字....)
原来正确的作法是 **给予 path 时就使用 unicode** ::
>>> import os; A = os.listdir(u'.'); A
[u'\u57fa\uf90a']
往後所有字串都使用 unicode 操作, 就不会爆炸了
据说事实上 M$ Windows 存档名就是用 unicode
我还没找到 "nt" 这个内建的 module 的 source code ,
还不清楚它是 怎麽实作/呼叫哪个函数 的
--
因为 BBS 上不吃 u'\uf90a', 所以直接从上面文字叙述中复制 "金" 字是没用的喔!
当我复制贴上文章的那一瞬间, u'\uf90a' 又被转成 u'\u91d1' 了...
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 140.113.136.219
1F:→ uranusjr:Windows 是用 UTF-16, 不过以微软的语言这个是叫 Unicode 02/28 02:03
2F:推 zha0:我以前也遇过, 那时用 python 2.x, 最後用 win32 api 找档 03/01 13:26
3F:→ apua:敢问楼上 win32api 如何取得档名 (eg: listdir 功能)? 03/03 15:48
4F:→ apua:因为我们曾试着找过但失败了 (win32api 文件写的有点差?) 03/03 15:49
6F:→ apua:thx 03/04 09:41