2012-08-08 55 views
5

从Python 2.7版加载Unicode文本正确的方法是这样的:如何在Python 2.7中一次解码unicode一行?

content = open('filename').read().decode('encoding'): 
for line in content.splitlines(): 
    process(line) 

更新:不,它是看不到答案。)

但是,如果该文件是非常大的时候,我可能需要一次读取,解码和处理它,这样整个文件就不会一次加载到内存中。喜欢的东西:

for line in open('filename'): 
    process(line.decode('encoding'))   

for循环的在开放的文件句柄迭代是一个生成器,一次读取一行。

这不工作,虽然,因为如果该文件是UTF32编码,例如,然后将文件中的字节(十六进制)看起来像:

hello\n = 68000000(h) 65000000(e) 6c000000(l) 6c000000(l) 6f000000(o) 0a000000(\n) 

而且分成所做线所述for环分割的\n字符的0a字节,从而导致(在十六进制):

lines[0] = 0x 68000000 65000000 6c000000 6c000000 6f000000 0a 
lines[1] = 0x 000000 

所以\n字符的一部分则留在第1行的端部,并且剩余的三个字节中终止第2行(接着是实际上在第2行中的任何文本。)在这些行中的任一行上调用decode可以理解为导致UnicodeDecodeError

UnicodeDecodeError: 'utf32' codec can't decode byte 0x0a in position 24: truncated data 

所以,很明显的是,在0a字节分裂Unicode字节流不是将其分割成线的正确方法。相反,我应该分裂出现的全四字节换行符(0x0a000000)。不过,我认为检测这些字符的正确方法是将字节流解码为一个Unicode字符串并查找\n个字符 - 而完整流的解码正是我试图避免的操作。

这不是一个不常见的要求。处理它的正确方法是什么?使用的编解码器模块

+1

您是否尝试使用codecs.open()方法读取文件? – 2012-08-08 14:25:28

+0

@Maulwurfn,我不知道它存在!但我现在做。谢谢。 – 2012-08-08 15:43:27

回答

1

codecs.open itself notes that io.open is a better option(注意正好在链接目标上方)。它不被弃用,但仅仅是因为它支持一些深奥的用途(字节 - >字节编解码器)。

io.open is available in Python 2.6 and higher,并提供相同的行为作为PY3的内置open,更好的优化,并且不会胡作非为喜欢codecs.open当它涉及到的东西像行结束转换。使用codecs.open的唯一原因是如果您需要支持Python 2.5及更早版本,否则,io.open会更好。

import io 

# Use with statement for guaranteed, predictable cleanup 
with io.open('filename', encoding='utf-32') as f: 
    for line in f: 
     process(line) 

顺便说一句,你可以转换任何已经打开二进制文件对象的无缝解码基于文本的对象using io.TextIOWrapper,所以如果别人提供你以二进制模式现有的类文件对象,你仍然可以做一行一行地隐含解码:

def process_file(f): 
    if 'b' in f.mode: # Or some better test... 
     f = io.TextIOWrapper(f, encoding='utf-32') 
    for line in f: 
     process(line) 
4

尝试:

for line in codecs.open(filename, encoding='utf32'): 
    do_something(line) 
+0

我选择@西蒙的回答只是'因为他有少点,但有一个upvote。谢谢! – 2012-08-08 14:38:46

+0

咦?现在你只有一点!发生了什么!?!?! – 2012-09-24 11:10:17

7

如何试图somethng像:

for line in codecs.open("filename", "rt", "utf32"): 
    print line 

我认为这应该工作。

codecs模块应该为您做翻译。

+0

读者!另请参阅本页底部附近的ShadowRanger的低点答案:“codecs.open docs注意io.open是更好的选择”... – 2016-10-14 13:02:00

1

使用codecs.open而不是内置的开放:

import codecs 
for line in codecs.open('filename', encoding='encoding'): 
    print repr(line) 

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

当然,我完成我精心制作的计算器问题后,发现这只是瞬间。

+0

@jamylak,感谢您修复我的伪装代码。 – 2012-08-08 14:37:31

+0

没问题,但我只修复了缩进:) – jamylak 2012-08-08 14:39:21