我有一个 UTF-8 文件,其中一些行包含 U+2028 行分隔符字符(http://www.fileformat.info/info/unicode/char/2028/index.htm)。当我从文件中读取行时,我不希望它被视为换行符。当我遍历文件或使用 readlines() 时,有没有办法将它从分隔符中排除?(除了将整个文件读入一个字符串,然后用 \n 分割。)谢谢!
5 回答
我无法重现这种行为,但这是一个简单的解决方案,它只是合并 readline 结果,直到它们不以 U+2028 结尾。
#!/usr/bin/env python
from __future__ import with_statement
def my_readlines(f):
buf = u""
for line in f.readlines():
uline = line.decode('utf8')
buf += uline
if uline[-1] != u'\u2028':
yield buf
buf = u""
if buf:
yield buf
with open("in.txt", "rb") as fin:
for l in my_readlines(fin):
print l
我无法在 mac os x 上的 python 2.5、2.6 或 3.0 中复制此行为 - U+2028 始终被视为非结束行。您能否更详细地了解您在哪里看到此错误?
也就是说,这是“文件”类的一个子类,它可能会做你想做的事:
#/usr/bin/python
# -*- coding: utf-8 -*-
class MyFile (file):
def __init__(self, *arg, **kwarg):
file.__init__(self, *arg, **kwarg)
self.EOF = False
def next(self, catchEOF = False):
if self.EOF:
raise StopIteration("End of file")
try:
nextLine= file.next(self)
except StopIteration:
self.EOF = True
if not catchEOF:
raise
return ""
if nextLine.decode("utf8")[-1] == u'\u2028':
return nextLine+self.next(catchEOF = True)
else:
return nextLine
A = MyFile("someUnicode.txt")
for line in A:
print line.strip("\n").decode("utf8")
感谢大家的回答。我想我知道为什么您可能无法复制它。我刚刚意识到,如果我在打开文件时解码文件,就会发生这种情况,如下所示:
f = codecs.open(filename, encoding='utf-8')
for line in f:
print line
如果我先打开文件然后解码各个行,则这些行在 u2028 上没有分隔:
f = open(filename)
for line in f:
print line.decode("utf8")
(我在 Windows 上使用 Python 2.6。该文件最初是 UTF16LE,然后被转换为 UTF8)。
这很有趣,我想从现在开始我不会使用 codecs.open 了:-)。
如果您使用 Python 3.0(请注意,我没有,所以我无法测试),根据文档,您可以传递一个可选newline
参数来open
指定要使用的行分隔符。但是,文档根本没有提到 U+2028(它只提到\r
,\n
和\r\n
作为行分隔符),所以这甚至发生对我来说实际上是一个惊喜(尽管我可以用 Python 2.6 确认这一点)。
编解码器模块正在做正确的事情。U+2028 被命名为“LINE SEPARATOR”,并带有注释“可用于明确表示此语义”。因此将其视为行分隔符是明智的。
大概创建者不会没有充分的理由将 U+2028 个字符放在那里……文件也有 u"\n" 吗?为什么你不希望在 U+2028 上分割行?