У меня есть файл в UTF-8, где некоторые строки содержат символ разделителя строк U+2028 (http://www.fileformat.info/info/unicode/char/2028/index.htm). Я не хочу, чтобы это рассматривалось как разрыв строки, когда я читаю строки из файла. Есть ли способ исключить его из разделителей, когда я перебираю файл или использую readlines()? (Помимо чтения всего файла в строку и последующего разделения на \n.) Спасибо!
Как исключить U + 2028 из разделителей строк в Python при чтении файла?
Ответы (5)
Я не могу повторить это поведение в python 2.5, 2.6 или 3.0 на mac os x — 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")
if nextLine.decode("utf8")[-1] == u'\u2028':
Я получал предупреждение без оператора декодирования, не совсем понимаю, почему.
- person Markus; 10.07.2009
Я не мог воспроизвести такое поведение, но вот наивное решение, которое просто объединяет результаты строки чтения до тех пор, пока они не заканчиваются на 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
Спасибо всем за ответ. Думаю, я знаю, почему вы, возможно, не смогли воспроизвести это. Я только что понял, что это происходит, если я декодирую файл при открытии, например:
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")
(Я использую Python 2.6 в Windows. Первоначально файл был UTF16LE, а затем он был преобразован в UTF8).
Это очень интересно, думаю, теперь я не буду часто использовать codecs.open :-).
Если вы используете Python 3.0 (обратите внимание, что я этого не делаю, поэтому я не могу тестировать), в соответствии с документация, вы можете передать необязательный параметр newline
в open
, чтобы указать, какой разделитель строк использовать. Однако в документации вообще не упоминается U + 2028 (в качестве разделителей строк упоминаются только \r
, \n
и \r\n
), поэтому для меня на самом деле удивительно, что это вообще происходит (хотя я могу подтвердить это даже с Python 2.6) .
Модуль кодеков делает ПРАВИЛЬНУЮ вещь. U + 2028 назван «РАЗДЕЛИТЕЛЬ СТРОКИ» с комментарием «может использоваться для однозначного представления этой семантики». Поэтому разумно рассматривать его как разделитель строк.
Предположительно, создатель не стал бы помещать туда символы U + 2028 без уважительной причины ... в файле также есть u"\n"? Почему вы хотите, чтобы строки в U+2028 не разделялись?