Вопрос

Мне нужна функция, которая выполняет итерацию по всем строкам в файле.
Вот что у меня есть на данный момент:

def LineFeed(file):
    ret = ""
    for byte in file:
        ret = ret + str(byte)
        if str(byte) == '\r':
            yield ret
            ret = ""

Все строки в файле заканчиваются на (не ), и я читаю это в "rb" режим, (я должен прочитать этот файл в двоичном формате).В yield не работает и ничего не возвращает.Может быть, есть проблема со сравнением?Я просто не уверен, как вы представляете байт / символ в python.

У меня возникает идея, что если вы выполняете цикл for для файла "rb", он все равно пытается выполнить итерацию по строкам, а не по байтам ..., как я могу выполнить итерацию по байтам?Моя проблема в том, что у меня нет стандартных окончаний строк.Также мой файл заполнен 0x00 байтами, и я хотел бы избавиться от них всех, поэтому я думаю, что мне понадобится вторая функция yield, как я мог бы это реализовать, я просто не знаю, как представить 0x00 байт в python или нулевой символ.

Это было полезно?

Решение

Если вы сами решаете, как открывать файл, я бы рекомендовал открывать его с помощью универсального перевода строки, поскольку не распознается как символ перевода строки, если вы просто используете режим 'rb', но распознается, если вы используете 'Urb'.

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

Предполагая, что вы хотите, чтобы полученные вами строки по-прежнему были \ r завершены:

NUL = '\x00'
def lines_without_nulls(path):
    with open(path, 'Urb') as f:
        for line in f:
            yield line.replace(NUL, '').replace('\n', '\r')

Другие советы

Я думаю, что вас смущает то, что делает "for x in file".Предполагая, что вы получили свой дескриптор типа "file = open (имя_файла)", byte в этом случае будет целой строкой, а не одним символом.Таким образом, вы вызываете yield только тогда, когда вся строка состоит из одного возврата каретки.Попробуйте изменить "байт" на "строку" и повторить это со вторым циклом.

Возможно, если бы вы объяснили, что представляет собой этот файл, почему в нем много '\x00', почему вы считаете, что вам нужно прочитать его в двоичном режиме, мы могли бы помочь вам с вашей основной проблемой.

В противном случае попробуйте следующий код;это позволяет избежать какой-либо зависимости от соглашения о конце строки вашей операционной системы (или вмешательства со стороны него).

lines = open("the_file", "rb").read().split("\r")
for line in lines:
    process(line)

Редактировать:нулевой байт ASCII (не "NULL") равен "\x00".

Итак, ваша проблема заключается в переборе строк файла, открытого в двоичном режиме, которые используют '\r' в качестве разделителя строк.Поскольку файл находится в двоичном режиме, вы не можете использовать универсальную функцию перевода строки, и получается, что '\r' не интерпретируется как разделитель строк в двоичном режиме.

Чтение файла char за char - ужасно неэффективная вещь в Python, но вот как вы могли бы выполнить итерацию по вашим строкам:

def cr_lines(the_file):
    line = []
    while True:
        byte = the_file.read(1)
        if not byte:
            break
        line.append(byte)
        if byte == '\r':
            yield ''.join(line)
            line = []
    if line:
        yield ''.join(line)

Чтобы быть более эффективным, вам нужно было бы читать большие фрагменты текста и обрабатывать буферизацию в вашем итераторе.Имея в виду, что вы можете получить странные ошибки при поиске во время итерации.Для предотвращения этих ошибок потребуется подкласс file, чтобы вы могли очищать буфер при поиске.

Обратите внимание на использование ''.join(line) идиома.Накапливая строку с += имеет ужасную производительность и является распространенной ошибкой, допускаемой начинающими программистами.

Редактировать:

  • string1 += string2 конкатенация строк происходит медленно.Попробуйте объединить список строк.

  • ddaa прав - вам не должны понадобиться struct пакет, если двоичный файл содержит только ASCII.Кроме того, мой генератор возвращает строку после окончательного ' ', перед EOF.С этими двумя незначительными исправлениями мой код подозрительно похож (практически идентичен) на этот более свежий ответ.

Фрагмент кода:

def LineFeed(f):
    ret = []
    while True:
        oneByte = f.read(1)
        if not oneByte: break
        # Return everything up to, but not including the carriage return
        if oneByte == '\r':
            yield ''.join(ret)
            ret = []
        else:
            ret.append(oneByte)
    if oneByte:
        yield ''.join(ret)
if __name__ == '__main__':
    lf = LineFeed( open('filename','rb') )

    for something in lf:
        doSomething(something)
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top