python实现读取文件 - python读取unicode文件



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

\ x ...序列是Python专用的。 这不是一个通用的字节转义序列。

如何以UTF-8编码的非ASCII码实际输入取决于您的操作系统和/或您的编辑器。 这是你如何在Windows中完成的 。 要让OS X输入一个尖锐的口音,你可以选择 + E ,然后选择A ,OS X中几乎所有的文本编辑器都支持UTF-8。

https://src-bin.com

理解阅读和写文本到文件(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'

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

然后:

>>> 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'

我在这里不了解什么? 显然,我有一些重要的魔法(或者说是有意义的),我错过了。 一个人输入到文本文件中以获得适当的转换?

如果你真的无法让Python识别它,那么当它来自外部时,我真正无法理解的是UTF-8表示的意义。 也许我应该只是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'

Answer #1

你已经无意中发现了编码的一般问题:我怎么知道文件是在哪一种编码?

答案: 除非文件格式规定了这一点, 否则你不能。 例如,XML从以下开始:

<?xml encoding="utf-8"?>

这个头文件经过精心挑选,因此无论编码如何都可以读取。 在你的情况下,没有这样的提示,因此你的编辑和Python都不知道发生了什么。 因此,您必须使用codecs模块并使用codecs.open(path,mode,encoding) ,它提供了Python中缺少的位。

至于你的编辑器,你必须检查它是否提供了设置文件编码的方法。

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'

问:我认为这里有一些遗漏:文件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应该变成“à”,但计算机无法知道,所以您必须通过指定编写文件时使用的编码来告诉它。


Answer #2

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

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

Answer #3

您还可以改进原始的open()函数,以便使用Unicode函数使用Unicode函数替换原文。 这种解决方案的美妙之处在于您无需更改任何旧代码。 它是透明的。

import codecs
import functools
open = functools.partial(codecs.open, encoding='utf-8')

Answer #4

我试图用Python 2.7.9解析iCal

从icalendar导入日历

但我得到:

 Traceback (most recent call last):
 File "ical.py", line 92, in parse
    print "{}".format(e[attr])
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe1' in position 7: ordinal not in range(128)

它只是修复了:

print "{}".format(e[attr].encode("utf-8"))

(现在它可以打印likéáböss。)


Answer #5

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

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

有一些不常用的编解码器在这里很有用。 这个特定的读取允许从Python内部采用UTF-8表示法,将它们复制到ASCII文件中,并将它们读入Unicode。 在“字符串转义”解码下,斜线不会翻倍。

这允许我想象的那种往返行程。


Answer #6

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

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

用于python驱动的http服务器。


Answer #7

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

如果你想用Python读写编码文件,最好使用codecs模块。

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

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

然后将此字符串粘贴到您的编辑器中,并确保它使用Latin-1存储它。 在假定剪贴板不会让字符串乱码的情况下,往返应该是有效的。


Answer #8
# -*- 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()




io