2016-04-20 2 views
-1

Как я могу напечатать последнюю строку в текстовом файле около 612 MB и имеет около 4 миллионов строк текста, состоящих из This is a line. До сих пор у меня есть:Как я могу напечатать последнюю строку в большом текстовом файле?

File.py

f = open("foo.txt","r+") 
datalist = [] 
for line in f: 
    datalist.append(line) 
print(datalist[-1]) 

Единственная проблема, которую я вижу с моим кодом, что он использует много памяти. Я слышал, что люди использовали os.lseek, но я не знаю, как его реализовать.

+2

Вызов 'tail' через' subprocess'? Он читает файл назад. Невозможно побить это (за исключением повторного использования его в python). Вы в Linux? – jDo

+0

@jDo К сожалению, я нахожусь в Windows 10 –

+0

'print (« Это строка »)'? Я не уверен, как буквально взять ваше описание формата ввода. – user2357112

ответ

2

Если вам нужна только последняя строка, выбросьте все остальное.

with open('foo.txt') as f: 
    for line in f: 
     pass 

# `line` is the last line of the file. 

Гораздо быстрее (но гораздо менее читаемым) было бы начать в конце файла и двигаться в обратном направлении по байтам, пока не найдете \n, то читайте.

with open('foo.txt') as f: 
    fd = f.fileno() 
    os.lseek(fd, 0, os.SEEK_END) 
    while True: 
     ch = os.read(fd, 1) 
     if ch == b'\n': 
      line = f.read() 
      break 
     else: 
      os.lseek(fd, -2, os.SEEK_CUR) 

# `line` is the last line of the file 

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

+0

Когда я запустил ваш код, я получил 'TypeError: требуется целое число (получило тип _io.TextIOWrapper)' –

+0

@Alex, который исправлен. –

+1

Эффективность решения для чтения-назад может быть улучшена путем поиска и чтения в кусках и использования 'rfind' для поиска последнего' '\ n''. Кроме того, обработка новых строк в качестве последнего символа файла довольно тонкая (код ищет до конца, ничего не читает, а затем возвращает два символа, пропуская последний символ файла! Я думаю, что это фактически дает правильный результат , но это не очевидно на первый взгляд.) В идеале, также должна быть некоторая обработка, если есть только одна строка, и вы в конечном итоге пытаетесь искать левую часть файла или если файл пуст. – user2357112

0

Вот очень простое усовершенствование, которое хранит только одну строку, в то время:

f = open("foo.txt","r") 
data = None 
for line in f: 
    data = line 
print(data) 

Или вы можете подобрать значение окончательного цикла после цикла:

f = open("foo.txt","r") 
line = None 
for line in f: 
    pass 
print(line) 

Заметим, что в этом Например, line будет None, если файл пуст (что является причиной первоначального присвоения line).

0

Быстрое улучшение было бы просто выбросить datalist и сохранить только самую последнюю строку, так как это все, о чем вы заботитесь.

f = open("foo.txt","r+") 
for line in f: 
    pass 
print(line) 

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

0

Вам не нужно добавлять каждую строку в список. Просто используйте переменную цикла:

line = None # prevents a NameError if the file is empty 

with open("foo.txt", "r+") as f: 
    for line in f: 
     pass 
print(line) 
0

Заканчивать Deque в коллекции модуля. Существует рецепт для поиска последнего «n» количества строк в файле; т.е. хвостом.

https://docs.python.org/2/library/collections.html#deque-recipes

def tail(filename, n=10): 
    'Return the last n lines of a file' 
    return deque(open(filename), n) 
+0

Кажется, что это будет намного менее результативно, чем текущий метод OP. –