Метод Tell () не надежен при работе с текстовыми файлами в Python - PullRequest
1 голос
/ 19 мая 2019

Кажется, что метод .tell () не очень надежен при работе с текстовыми файлами в python. Я пытаюсь использовать этот метод, чтобы заменить условие EOF, как в других языках программирования.

По разным причинам я не хочу перебирать текстовый файл с циклом FOR, а вместо этого использую цикл WHILE.

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

import re
from random import randint


def file_len_lines(f_name):
    with open(f_name) as f:
        for i, l in enumerate(f):
            pass
    return i + 1


def file_len_chars(f_name, with_nls):
    char_count = 0
    with open(f_name) as f:
        for line in f:
            char_count += len(line)
            if with_nls:
                char_count += 1
            else:
                pass
    return char_count


def trim(sut):
    return re.sub(' +', ' ', sut).strip()


# Create test file
with open("test.txt", "w") as f:
    word_list = ("Betty Eats Cakes And Uncle Sells Eggs "*20).split()
    word_list[3] = ""
    # for num in range(len(word_list)):
    #     if randint(1, 2) == 1:
    #         word_list[num] = ""
    for word in word_list:
        print(word, file=f)

file_to_read = 'test.txt'
# file_to_read = 'Fibonacci Tree 01.log'


with open(file_to_read, "r") as f:
    count = 0
    file_length = file_len_chars(file_to_read, True)
    file_length_lines = file_len_lines(file_to_read)
    print(f"Lines in file = {file_length_lines}, Characters in file = {file_length}")
    f.seek(0)
    while f.tell() < file_length:
        count += 1
        text_line = f.readline()
        print(f"Line = {count}, ", end="")
        print(f"Tell = {f.tell()}, ", end="")
        print(f"Length {len(text_line)} ", end="")
        if text_line in ['', '\n']:
            print(count)
        elif trim(text_line).upper()[0] in "A E I O U".split():
            print(text_line, end='')
        else:
            print(count)

Этот код должен всегда выводить что-то вроде:

Lines in file = 140, Characters in file = 897
Line = 1, Tell = 7, Length 6 1
Line = 2, Tell = 13, Length 5 Eats
Line = 3, Tell = 20, Length 6 3
...
Line = 138, Tell = 884, Length 6 Uncle
Line = 139, Tell = 891, Length 6 139
Line = 140, Tell = 897, Length 5 Eggs

Process finished with exit code 0

но вместо этого он в основном выводит что-то похожее на:

Lines in file = 140, Characters in file = 605
Line = 1, Tell = 7, Length 6 1
Line = 2, Tell = 18446744073709551630, Length 5 Eats

Process finished with exit code 0

Вы можете видеть, что в последней строке вывода выше вывод метода .tell () стал бесполезным и не прошел все 140 строк.

Я ищу способ заставить метод .tell () вести себя или иным образом обнаруживать условие EOF другим способом, чтобы прервать цикл WHILE.

Опять же, большинство советов, найденных в Интернете, гласят: "итерация с циклом FOR" Я не хочу делать это по разным причинам, которые утомительно объяснять. (Вкратце, это сделает мою исходную программу очень громоздкой из-за вложенной блок-схемы, которой я собираюсь следовать.)

...