当前位置:  开发笔记 > 编程语言 > 正文

Unicode(UTF-8)在Python中读取和写入文件

如何解决《Unicode(UTF-8)在Python中读取和写入文件》经验,为你挑选了10个好方法。

我在理解文本读取和写入文件时遇到了一些大脑失败(Python 2.4).

# The string, which has an a-acute in it.
ss = u'Capit\xe1n'
ss8 = ss.encode('utf8')
repr(ss), repr(ss8)

("u'Capit\xe1n'","'Capit\xc3\xa1n'")

print ss, ss8
print >> open('f1','w'), ss8

>>> file('f1').read()
'Capit\xc3\xa1n\n'

所以我输入Capit\xc3\xa1n我最喜欢的编辑器,在文件f2中.

然后:

>>> open('f1').read()
'Capit\xc3\xa1n\n'
>>> open('f2').read()
'Capit\\xc3\\xa1n\n'
>>> open('f1').read().decode('utf8')
u'Capit\xe1n\n'
>>> open('f2').read().decode('utf8')
u'Capit\\xc3\\xa1n\n'

我在这里不理解什么?显然,我缺少一些重要的魔法(或者很有道理).在文本文件中键入什么来获得正确的转换?

我真正没有想到的是,UTF-8表示的重点是,如果你真的不能让Python识别它,那么它来自外部.也许我应该只是JSON转储字符串,并使用它,因为它有一个asciiable表示!更重要的是,当从文件进入时,Python会识别和解码这个Unicode对象的ASCII表示吗?如果是这样,我怎么得到它?

>>> print simplejson.dumps(ss)
'"Capit\u00e1n"'
>>> print >> file('f3','w'), simplejson.dumps(ss)
>>> simplejson.load(open('f3'))
u'Capit\xe1n'

Tim Swast.. 678

我没有弄乱编码和解码方法,而是在打开文件时更容易指定编码.该io模块(在Python 2.6中添加)提供了一个io.open具有编码参数的函数.

使用io模块中的open方法.

>>>import io
>>>f = io.open("test", mode="r", encoding="utf-8")

然后在调用f的read()函数之后,返回编码的Unicode对象.

>>>f.read()
u'Capit\xe1l\n\n'

请注意,在Python 3中,该io.open函数是内置函数的别名open.内置的open函数仅支持Python 3中的encoding参数,而不支持Python 2.

编辑:以前这个答案推荐编解码器模块.该混合编解码器时,模块可能会造成问题read()readline(),所以这个答案现在建议的IO模块来代替.

使用编解码器模块中的open方法.

>>>import codecs
>>>f = codecs.open("test", "r", "utf-8")

然后在调用f的read()函数之后,返回编码的Unicode对象.

>>>f.read()
u'Capit\xe1l\n\n'

如果您知道文件的编码,那么使用编解码器包将会更加容易混淆.

请参阅http://docs.python.org/library/codecs.html#codecs.open



1> Tim Swast..:

我没有弄乱编码和解码方法,而是在打开文件时更容易指定编码.该io模块(在Python 2.6中添加)提供了一个io.open具有编码参数的函数.

使用io模块中的open方法.

>>>import io
>>>f = io.open("test", mode="r", encoding="utf-8")

然后在调用f的read()函数之后,返回编码的Unicode对象.

>>>f.read()
u'Capit\xe1l\n\n'

请注意,在Python 3中,该io.open函数是内置函数的别名open.内置的open函数仅支持Python 3中的encoding参数,而不支持Python 2.

编辑:以前这个答案推荐编解码器模块.该混合编解码器时,模块可能会造成问题read()readline(),所以这个答案现在建议的IO模块来代替.

使用编解码器模块中的open方法.

>>>import codecs
>>>f = codecs.open("test", "r", "utf-8")

然后在调用f的read()函数之后,返回编码的Unicode对象.

>>>f.read()
u'Capit\xe1l\n\n'

如果您知道文件的编码,那么使用编解码器包将会更加容易混淆.

请参阅http://docs.python.org/library/codecs.html#codecs.open


也适用于编写文件,而不是"打开(文件,'w')`do`codecs.open(文件,'w','utf-8')`已解决
`codecs.open(...)`方法是否也完全符合`with open(...):`style,其中`with`关注完毕后关闭文件?无论如何它似乎工作.
我希望我可以投票一百次.在对由大量混合数据引起的编码问题以及关于编码的交叉阅读之后痛苦了几天之后,这个答案就像沙漠中的水一样.希望我早点见到它.
@ try-catch-finally是的.我一直使用`with codecs.open(...)作为f:`.

2> 小智..:

在符号中

u'Capit\xe1n\n'

"\ xe1"仅代表一个字节."\ x"告诉您"e1"是十六进制的.当你写作

Capit\xc3\xa1n

在你的文件中你有"\ xc3".这些是4个字节,在您的代码中,您可以全部阅读它们.您可以在显示它们时看到:

>>> open('f2').read()
'Capit\\xc3\\xa1n\n'

您可以看到反斜杠是通过反斜杠转义的.所以你的字符串中有四个字节:"\","x","c"和"3".

编辑:

正如其他人在答案中指出的那样,您只需在编辑器中输入字符,然后编辑器就应该处理转换为UTF-8并保存.

如果您实际拥有此格式的字符串,则可以使用string_escape编解码器将其解码为普通字符串:

In [15]: print 'Capit\\xc3\\xa1n\n'.decode('string_escape')
Capitán

结果是一个以UTF-8编码的字符串,其中重音字符由\\xc3\\xa1原始字符串中写入的两个字节表示.如果你想拥有一个unicode字符串,你必须使用UTF-8再次解码.

编辑:您的文件中没有UTF-8.要实际看到它的样子:

s = u'Capit\xe1n\n'
sutf8 = s.encode('UTF-8')
open('utf-8.out', 'w').write(sutf8)

将文件utf-8.out内容与您使用编辑器保存的文件内容进行比较.


令人惊讶的是,有多少英国程序员说"只使用ascii"然后没有意识到£符号不是它.大多数人都不知道ascii!=本地代码页(即latin1).
尝试阅读本文作为入门:http://www.joelonsoftware.com/articles/Unicode.html
答案是你的"那么,有什么意义......"问题是"穆".(因为Python可以读取以UTF-8编码的文件).对于第二个问题:\ xc3不是ASCII集的一部分.也许你的意思是"8位编码".您对Unicode和编码感到困惑; 没关系,很多都是.

3> Dakusan..:

现在你在Python3中所需要的只是 open(Filename, 'r', encoding='utf-8')

[编辑于2016-02-10进行要求澄清]

Python3将编码参数添加到其open函数中.以下是有关open函数的信息:https://docs.python.org/3/library/functions.html#open

open(file, mode='r', buffering=-1, 
      encoding=None, errors=None, newline=None, 
      closefd=True, opener=None)

编码是用于解码或编码文件的编码的名称.这应该只在文本模式下使用.默认编码取决于平台(无论locale.getpreferredencoding() 返回),但可以使用Python支持的任何文本编码.有关支持的编码列表,请参阅编解码器模块.

因此,通过添加encoding='utf-8'作为open函数的参数,文件读取和写入都是以utf8(现在也是Python中所有内容的默认编码)完成的.


它看起来在python 2中可以使用编解码器模块 - `codecs.open('somefile',encoding ='utf-8')`http://stackoverflow.com/a/147756/149428

4> Gregg Lind..:

所以,我找到了一个我正在寻找的解决方案,它是:

print open('f2').read().decode('string-escape').decode("utf-8")

有一些不寻常的编解码器在这里很有用.这个特殊的读取允许人们从Python中获取UTF-8表示,将它们复制到ASCII文件中,并将它们读入Unicode.在"string-escape"解码下,斜杠不会加倍.

这允许我想象的那种往返旅行.



5> 小智..:
# -*- encoding: utf-8 -*-

# converting a unknown formatting file in utf-8

import codecs
import commands

file_location = "jumper.sub"
file_encoding = commands.getoutput('file -b --mime-encoding %s' % file_location)

file_stream = codecs.open(file_location, 'r', file_encoding)
file_output = codecs.open(file_location+"b", 'w', 'utf-8')

for l in file_stream:
    file_output.write(l)

file_stream.close()
file_output.close()



6> 小智..:

实际上,这对我在Python 3.2中使用UTF-8编码读取文件很有用:

import codecs
f = codecs.open('file_name.txt', 'r', 'UTF-8')
for line in f:
    print(line)



7> Aaron Digull..:

您已经无意中发现了编码的一般问题:如何判断文件的编码方式?

答:除非文件格式规定,否则你不能这样做.例如,XML以以下内容开头:


仔细选择此标头,以便无论编码如何都可以读取.在你的情况下,没有这样的提示,因此你的编辑和Python都不知道发生了什么.因此,您必须使用在Python中提供缺失位的codecs模块和用法codecs.open(path,mode,encoding).

对于您的编辑器,您必须检查它是否提供了一些设置文件编码的方法.

UTF-8的要点是能够将21位字符(Unicode)编码为8位数据流(因为这是世界上所有计算机都能处理的唯一内容).但由于大多数操作系统早于Unicode时代,因此它们没有合适的工具将编码信息附加到硬盘上的文件中.

下一个问题是Python中的表示.这在heikogerlach的评论中得到了很好的解释.您必须了解您的控制台只能显示ASCII.为了显示Unicode或任何> = charcode 128,它必须使用一些转义方法.在编辑器中,您不能键入转义的显示字符串,而是键入字符串的含义(在这种情况下,您必须输入变音符号并保存文件).

也就是说,您可以使用Python函数eval()将转义字符串转换为字符串:

>>> x = eval("'Capit\\xc3\\xa1n\\n'")
>>> x
'Capit\xc3\xa1n\n'
>>> x[5]
'\xc3'
>>> len(x[5])
1

如您所见,字符串"\ xc3"已变为单个字符.现在这是一个8位字符串,UTF-8编码.要获得Unicode:

>>> x.decode('utf-8')
u'Capit\xe1n\n'

Gregg Lind问:我认为这里缺少一些部分:文件f2包含:hex:

0000000: 4361 7069 745c 7863 335c 7861 316e  Capit\xc3\xa1n

codecs.open('f2','rb', 'utf-8')例如,在一个单独的字符中读取所有字符(预期)是否有任何方法可以写入ASCII中的文件?

答:这取决于你的意思.ASCII不能代表字符> 127.所以你需要一些方法来说"接下来的几个字符意味着特殊的东西"这就是序列"\ x"的作用.它说:接下来的两个字符是单个字符的代码."\ u"使用四个字符将Unicode编码为0xFFFF(65535).

因此,您无法直接将Unicode写入ASCII(因为ASCII不包含相同的字符).你可以把它写成字符串转义(如f2中所示); 在这种情况下,该文件可以表示为ASCII.或者您可以将其写为UTF-8,在这种情况下,您需要一个8位安全流.

您使用的解决方案decode('string-escape')确实有效,但您必须知道您使用了多少内存:使用量的三倍codecs.open().

请记住,文件只是一个8位字节序列.位和字节都没有意义.是你说"65意味着'A'".由于\xc3\xa1应该变成"à"但计算机无法知道,您必须通过指定编写文件时使用的编码来告诉它.



8> 小智..:

要读取Unicode字符串然后发送到HTML,我这样做:

fileline.decode("utf-8").encode('ascii', 'xmlcharrefreplace')

对于python驱动的http服务器很有用.



9> Ryan..:

除了之外codecs.open(),可以使用io.open()Python2或Python3来读/写unicode文件

import io

text = u'á'
encoding = 'utf8'

with io.open('data.txt', 'w', encoding=encoding, newline='\n') as fout:
    fout.write(text)

with io.open('data.txt', 'r', encoding=encoding, newline='\n') as fin:
    text2 = fin.read()

assert text == text2



10> Torsten Mare..:

好吧,你最喜欢的文本编辑器没有意识到\xc3\xa1应该是字符文字,但它将它们解释为文本.这就是你在最后一行得到双反斜杠的原因 - 它现在是xc3你文件中真正的反斜杠+ 等.

如果您想用Python读写编码文件,最好使用编解码器模块.

在终端和应用程序之间粘贴文本很困难,因为您不知道哪个程序将使用哪种编码来解释您的文本.您可以尝试以下方法:

>>> s = file("f1").read()
>>> print unicode(s, "Latin-1")
Capitán

然后将此字符串粘贴到编辑器中,并确保使用Latin-1存储它.假设剪贴板没有乱码,往返应该有效.

推荐阅读
李桂平2402851397
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有