使用日文字符时,OS X上的文件名编码为base64不正确

时间:2013-02-22 14:36:46

标签: python encoding python-2.7 base64 osx-mountain-lion

我有一堆以人名命名的文件(例如“john.txt”,“mary.txt”),但其中也有日文名称(例如“fūka.txt”,“tetsurō.txt”)。 / p>

我要做的是将“.txt”之前的名称转换为Base64。

唯一的问题是,当我拿一个文件名(没有扩展名)并使用基于网络的转换器时,我得到的结果与我的Python脚本的编码不同。

所以...例如,当我复制没有扩展名的文件名部分并在http://www.base64encode.org中编码“fūka”时,我得到“ZsWra2E =”。当我从UTF-8编码的PostgreSQL数据库中获取人名时,得到的结果与小写和base64编码相同。

但是当我使用下面的Python脚本时,我会得到“ZnXMhGth”

import glob, os
import base64

def rename(dir, pattern):
    for pathAndFilename in glob.iglob(os.path.join(dir, pattern)):

        title, ext = os.path.splitext(os.path.basename(pathAndFilename))

        t = title.lower().encode("utf-8")

        encoded_string = base64.b64encode(t) + ext

        p = os.path.join(dir, encoded_string)

        os.rename(pathAndFilename, p)

rename(u'./test', u'*.txt')

我在OS X 10.8和Linux(从Mac上传到Linux服务器的文件)中获得了相同的结果。 Python是2.7。我还尝试了PHP脚本(结果与Python脚本相同)。

当我使用其他字符的名称(例如“tetsurō”)时会发生类似的差异。

还有一件奇怪的事情......当我在OS X的终端应用程序中输出带有Python脚本的文件名部分然后将此文本复制为文件名...然后将文件名编码为base64时,我得到的结果与on相同我上面提到的网页。终端具有UTF-8编码。

有人可以解释一下我在做什么(或思考)错了吗?是否有某些小字符替换正在进行中?如何使Python脚本获得与上述网页相同的结果任何提示将不胜感激。

SOLUTION:

在Marks回答的帮助下,我修改了一个脚本,它就像一个魅力!谢谢Mark!

import glob, os
import base64
from unicodedata import normalize

def rename(dir, pattern):
    for pathAndFilename in glob.iglob(os.path.join(dir, pattern)):

        title, ext = os.path.splitext(os.path.basename(pathAndFilename))

        t = normalize('NFC', title.lower()).encode("utf-8") # <-- NORMALIZE !!!

        encoded_string = base64.b64encode(t) + ext

        p = os.path.join(dir, encoded_string)

        os.rename(pathAndFilename, p)

rename(u'./test', u'*.txt')

1 个答案:

答案 0 :(得分:0)

似乎Python脚本使用的是规范化形式的Unicode,其中ū已分为两个字符ucombining macron。另一种形式使用单个字符latin small letter u with macron。就Unicode而言,即使它们没有相同的二进制表示,它们也是相同的字符串。

您可以从此Unicode常见问题解答中获取更多信息:http://www.unicode.org/faq/normalization.html