Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/358.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
读取python中以不同编码选项保存的文件后的输出差异_Python_Unicode_Encoding_Utf 8 - Fatal编程技术网

读取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

我有一个unicode字符串列表文件,保存在编码选项utf-8中。我有另一个输入文件,保存在普通ansi中。我从该ansi文件中读取目录路径并执行os.walk(),并尝试匹配列表中是否存在任何文件(由utf-8保存)。但即使存在,也不匹配

后来,我用一个字符串“40M_195;z­µú¸ÕÀÉ”执行一些常规检查,并使用编码选项ansi、unicode和utf-8将这个特定字符串(来自记事本)保存在三个不同的文件中。我编写了一个python脚本来打印:

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
    的形式获得),但这会因机器而异。您可以使用名称
    mbcs
    从Windows上的Python中获取任何这种编码

  • “Unicode”是Windows用于UTF-16LE编码的名称(非常误导,因为Unicode是字符集标准,而不是任何类型的字节)⇔字符本身编码)。与ANSI和UTF-8不同,这不是ASCII兼容的编码,因此尝试从文件中读取一行失败,因为UTF-16LE中的行终止符不是
    \n
    ,而是
    \n\x00
    。这在上面的字节字符串的开头留下了一个虚假的
    \x00

  • “UTF-8”的命名至少是准确的,但Windows喜欢在其“UTF-8”文件的前面加上假字节顺序标记,这样在解码时会给您一个不需要的
    u'\uFEFF'
    字符。如果要接受从记事本保存的“UTF-8”文件,可以手动删除该文件或使用Python的
    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