Как исключить U + 2028 из разделителей строк в Python при чтении файла? - PullRequest
3 голосов
/ 09 июля 2009

У меня есть файл в UTF-8, где некоторые строки содержат символ разделителя строк U + 2028 (http://www.fileformat.info/info/unicode/char/2028/index.htm).. Я не хочу, чтобы он считался переносом строки при чтении строк из файла . Есть ли способ исключить его из разделителей, когда я перебираю файл или использую readlines ()? (Кроме чтения всего файла в строку и последующего разбиения на \ n.) Спасибо!

Ответы [ 5 ]

2 голосов
/ 09 июля 2009

Я не мог воспроизвести это поведение, но вот наивное решение, которое просто объединяет результаты 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
1 голос
/ 10 июля 2009

Спасибо всем за ответы. Я думаю, я знаю, почему вы, возможно, не смогли скопировать это. Я только что понял, что это произойдет, если я декодирую файл при открытии, как в:

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: -).

1 голос
/ 10 июля 2009

Я не могу продублировать это поведение в Python 2.5, 2.6 или 3.0 на Mac OS X - U + 2028 всегда рассматривается как не конец строки. Не могли бы вы подробнее рассказать о том, где вы видите эту ошибку?

Тем не менее, вот подкласс класса "file", который может делать то, что вы хотите:

#/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")
0 голосов
/ 10 июля 2009

Модуль кодеков делает ПРАВИЛЬНОЕ. U + 2028 называется «LINE SEPARATOR» с комментарием «может использоваться для однозначного представления этой семантики». Поэтому разумно рассматривать его как разделитель строк.

Предположительно, создатель не поместил бы туда символы U + 2028 без веской причины ... также есть ли в файле "u"? Почему вы хотите, чтобы строки не были разбиты на U + 2028?

0 голосов
/ 09 июля 2009

Если вы используете Python 3.0 (обратите внимание, что я не использую, поэтому я не могу тестировать), согласно документации , вы можете передать необязательный параметр newline в open, чтобы указать, какой линейный разделитель для использования. Тем не менее, в документации вообще не упоминается U + 2028 (в ней упоминаются только \r, \n и \r\n в качестве разделителей строк), так что на самом деле мне удивительно, что это даже происходит (хотя я могу подтвердить, это даже с Python 2.6).

...