在OS X上使用日文字符时文件名进行base64编码不正确

2 投票
1 回答
789 浏览
提问于 2025-04-17 16:46

我有一堆文件,文件名是人名,比如“john.txt”、“mary.txt”,但里面也有一些日本名字,比如“fūka.txt”、“tetsurō.txt”。

我想做的是把文件名中“.txt”之前的名字转换成Base64格式。

问题是,当我把文件名(不包括扩展名)放到一个网页转换器里时,得到的结果和我用Python脚本编码的结果不一样。

举个例子,当我复制文件名部分“fūka”,在http://www.base64encode.org上编码时,得到的是“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的终端应用中输出文件名部分,然后把这个文本复制作为文件名,再进行Base64编码时,得到的结果和我之前提到的网页上的结果是一样的。终端是UTF-8编码的。

有人能告诉我我哪里做错了(或者想错了)吗?中间是不是发生了什么小的字符替换?我该怎么让Python脚本得到和网页上相同的结果?任何提示都非常感谢。

解决方案:

在Mark的帮助下,我修改了脚本,结果非常好!谢谢你,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

看起来这个Python脚本使用了一种标准化的Unicode格式,其中的ū被分成了两个字符,分别是u和一个组合音符。而另一种形式则是用一个字符带音符的拉丁小写字母u。从Unicode的角度来看,虽然它们的二进制表示不同,但实际上它们是同一个字符串。

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

撰写回答