读取python中以不同编码选项保存的文件后的输出差异
我有一个unicode字符串列表文件,保存在编码选项utf-8中。我有另一个输入文件,保存在普通ansi中。我从该ansi文件中读取目录路径并执行os.walk(),并尝试匹配列表中是否存在任何文件(由utf-8保存)。但即使存在,也不匹配 后来,我用一个字符串“40M_195;zµú¸ÕÀÉ”执行一些常规检查,并使用编码选项ansi、unicode和utf-8将这个特定字符串(来自记事本)保存在三个不同的文件中。我编写了一个python脚本来打印:读取python中以不同编码选项保存的文件后的输出差异,python,unicode,encoding,utf-8,Python,Unicode,Encoding,Utf 8,我有一个unicode字符串列表文件,保存在编码选项utf-8中。我有另一个输入文件,保存在普通ansi中。我从该ansi文件中读取目录路径并执行os.walk(),并尝试匹配列表中是否存在任何文件(由utf-8保存)。但即使存在,也不匹配 后来,我用一个字符串“40M_195;zµú¸ÕÀÉ”执行一些常规检查,并使用编码选项ansi、unicode和utf-8将这个特定字符串(来自记事本)保存在三个不同的文件中。我编写了一个python脚本来打印: print repr(string) pr
print repr(string)
print string
输出如下所示:
ANSI编码UNICODE编码
UTF-8编码 我真的不明白如何比较来自不同编码文件的相同字符串。请帮忙。 PS:我有一些典型的unicode字符,如:唐朝小栗子第集.很难处理的mp3 我真的不明白如何比较来自不同编码文件的相同字符串 记事本使用三种不同的编码对字符串进行编码,从而产生三种不同的字节序列。要检索字符串,必须使用相同的编码对这些字节进行解码:
>>> ansi_bytes = '40M_\xc3z\xad\xb5\xb4\xfa\xb8\xd5\xc0\xc9'
>>> utf16_bytes = '4\x000\x00M\x00_\x00\xc3\x00z\x00\xad\x00\xb5\x00\xb4\x00\xfa\x00\xb8\x00\xd5\x00\xc0\x00\xc9\x00'
>>> utf8_bytes = '40M_\xc3\x83z\xc2\xad\xc2\xb5\xc2\xb4\xc3\xba\xc2\xb8\xc3\x95\xc3\x80\xc3\x89'
>>> ansi_bytes.decode('mbcs')
u'40M_\xc3z\xad\xb5\xb4\xfa\xb8\xd5\xc0\xc9' # 40M_Ãzµ´ú¸ÕÀÉ
>>> utf16_bytes.decode('utf-16le')
u'40M_\xc3z\xad\xb5\xb4\xfa\xb8\xd5\xc0\xc9' # 40M_Ãzµ´ú¸ÕÀÉ
>>> utf8_bytes.decode('utf-8')
u'40M_\xc3z\xad\xb5\xb4\xfa\xb8\xd5\xc0\xc9' # 40M_Ãzµ´ú¸ÕÀÉ
- “ANSI”(而不是“ASCI”)是Windows(有点误导性地)称其默认的特定于语言环境的代码页,在您的例子中是1252(西欧,您可以在Python中以
的形式获得),但这会因机器而异。您可以使用名称Windows-1252
从Windows上的Python中获取任何这种编码mbcs
- “Unicode”是Windows用于UTF-16LE编码的名称(非常误导,因为Unicode是字符集标准,而不是任何类型的字节)⇔字符本身编码)。与ANSI和UTF-8不同,这不是ASCII兼容的编码,因此尝试从文件中读取一行失败,因为UTF-16LE中的行终止符不是
,而是\n
。这在上面的字节字符串的开头留下了一个虚假的\n\x00
\x00
- “UTF-8”的命名至少是准确的,但Windows喜欢在其“UTF-8”文件的前面加上假字节顺序标记,这样在解码时会给您一个不需要的
字符。如果要接受从记事本保存的“UTF-8”文件,可以手动删除该文件或使用Python的u'\uFEFF'
编码UTF-8-sig
codecs.open()
而不是open()
来读取具有自动Unicode解码的文件。这也解决了UTF-16换行符问题,因为解码之后而不是之前检测到\n
字符
我从那个asci文件中读取目录路径并执行os.walk()
Windows文件名本机作为Unicode处理,因此当您给Windows一个字节字符串时,它必须猜测将这些字节转换为字符所需的编码。它选择ANSI而不是UTF-8。如果您使用的是同样用同一台机器的ANSI编码编码的文件中的字节字符串,那么这将很好,但是在这种情况下,您将被限制为适合您机器的区域设置的文件名。在西欧,4000万欧元唐朝小栗子第集.mp3将不会,因此您根本无法引用中文文件
Python支持将Unicode文件名直接传递给Windows,从而避免了这个问题(大多数其他语言无法做到这一点)。将Unicode字符串传递到文件系统函数中,如os.walk()
,您应该将Unicode字符串取出,而不是失败
因此,对于UTF-8编码的输入文件,类似于:
with codecs.open(u'directory_path.txt', 'rb', 'utf-8-sig') as fp:
directory_path = fp.readline().strip(u'\r\n') # unicode dir path
good_names = set()
with codecs.open(u'filename_list.txt', 'rb', 'utf-8-sig') as fp:
for line in fp:
good_names.add(line.strip(u'\r\n')) # set of unicode file names
for dirpath, dirnames, filenames in os.walk(directory path): # names will be unicode strings
for filename in filenames:
if filename in good_names:
# do something with file
说得好!出于某种原因,我把它记在心里了,我们在Python2中没有这样做。
'40M_\xc3\x83z\xc2\xad\xc2\xb5\xc2\xb4\xc3\xba\xc2\xb8\xc3\x95\xc3\x80\xc3\x89'
40M_Ãzµ´ú¸ÕÀÉ
>>> ansi_bytes = '40M_\xc3z\xad\xb5\xb4\xfa\xb8\xd5\xc0\xc9'
>>> utf16_bytes = '4\x000\x00M\x00_\x00\xc3\x00z\x00\xad\x00\xb5\x00\xb4\x00\xfa\x00\xb8\x00\xd5\x00\xc0\x00\xc9\x00'
>>> utf8_bytes = '40M_\xc3\x83z\xc2\xad\xc2\xb5\xc2\xb4\xc3\xba\xc2\xb8\xc3\x95\xc3\x80\xc3\x89'
>>> ansi_bytes.decode('mbcs')
u'40M_\xc3z\xad\xb5\xb4\xfa\xb8\xd5\xc0\xc9' # 40M_Ãzµ´ú¸ÕÀÉ
>>> utf16_bytes.decode('utf-16le')
u'40M_\xc3z\xad\xb5\xb4\xfa\xb8\xd5\xc0\xc9' # 40M_Ãzµ´ú¸ÕÀÉ
>>> utf8_bytes.decode('utf-8')
u'40M_\xc3z\xad\xb5\xb4\xfa\xb8\xd5\xc0\xc9' # 40M_Ãzµ´ú¸ÕÀÉ
with codecs.open(u'directory_path.txt', 'rb', 'utf-8-sig') as fp:
directory_path = fp.readline().strip(u'\r\n') # unicode dir path
good_names = set()
with codecs.open(u'filename_list.txt', 'rb', 'utf-8-sig') as fp:
for line in fp:
good_names.add(line.strip(u'\r\n')) # set of unicode file names
for dirpath, dirnames, filenames in os.walk(directory path): # names will be unicode strings
for filename in filenames:
if filename in good_names:
# do something with file