2009-05-30 3 views
2

У меня есть 2 простых вопроса о python:Два простых вопроса о python

1. Как получить количество строк файла в python?

2.Как найти местонахождение в файловом объекте на последней строке легко?

ответ

8

строки являются просто данными, разделенными символом новой строки '\n'.

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

count = 0 
for line in open('myfile'): 
    count += 1 
print count, line # it will be the last line 

2) чтение кусок от конца файла - самый быстрый способ найти последний символ новой строки.

def seek_newline_backwards(file_obj, eol_char='\n', buffer_size=200): 
    if not file_obj.tell(): return # already in beginning of file 
    # All lines end with \n, including the last one, so assuming we are just 
    # after one end of line char 
    file_obj.seek(-1, os.SEEK_CUR) 
    while file_obj.tell(): 
     ammount = min(buffer_size, file_obj.tell()) 
     file_obj.seek(-ammount, os.SEEK_CUR) 
     data = file_obj.read(ammount) 
     eol_pos = data.rfind(eol_char) 
     if eol_pos != -1: 
      file_obj.seek(eol_pos - len(data) + 1, os.SEEK_CUR) 
      break 
     file_obj.seek(-len(data), os.SEEK_CUR) 

Вы можете использовать это так:

f = open('some_file.txt') 
f.seek(0, os.SEEK_END) 
seek_newline_backwards(f) 
print f.tell(), repr(f.readline()) 
+0

э-э ... но что, если последняя строка содержит более 200 символов из EOF? – Triptych

+0

иногда строки обозначаются символом \ r; вы можете принять это во внимание. –

+0

@Michael Borgwardt: Хорошо, изменил код, чтобы принять это во внимание, теперь используемый символ является параметром функции. – nosklo

1

Единственный способ подсчета строк [что я знаю] будет читать все строки, например:

count = 0 
for line in open("file.txt"): count = count + 1 

После в цикле count будет указано количество строк.

0

Ответ на первый вопрос (остерегайтесь плохой производительности на больших файлов при использовании этого метода):

f = open("myfile.txt").readlines() 
print len(f) - 1 

Ответ на второй вопрос:

f = open("myfile.txt").read() 
print f.rfind("\n") 

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

+0

, который считывает весь файл в память сразу. – nosklo

+0

Я знаю, я специально отредактировал ответ, чтобы упомянуть об этом. – dpq

+0

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

2

Для небольших файлов, которые соответствуют памяти, как об использовании str.count() для получения количества строк файла:

line_count = open("myfile.txt").read().count('\n') 
+1

, который будет считывать весь файл в память сразу, поэтому я думаю, что цикл for лучше. – nosklo

+0

Человек, это 2009 год. Не привязывайтесь к старомодным пределам. –

+1

@Charlie Martin: Мне приходится иметь дело с текстовыми файлами легко до 4 ГБ. И это не связывает меня, лучше читать каждую строку за раз, а не весь файл, даже если он * вписывается * в память. OP является новичком и должен изучать хорошие практики, которые работают независимо от размера файла. – nosklo

7

Давайте не будем забывать

f = open("myfile.txt") 
lines = f.readlines() 

numlines = len(lines) 
lastline = lines[-1] 

ПРИМЕЧАНИЕ: это читает весь файл в памяти в виде списка. Помните об этом в том случае, если файл очень большой.

+2

, который также считывает весь файл в память сразу. – nosklo

+4

Да, и? Когда я писал бизнес-приложения в 8 КБ памяти, я мог бы заботиться. –

+1

@Charlie Martin: 1) Что делать, если файл составляет 4 ГБ? 2) Что делать, если я уже запускаю другое приложение, использующее мою память, и у меня есть только несколько МБ? Должен ли я ударить виртуальную память (своп)? В самом деле? – nosklo

5

самый простой способ - просто прочитать файл в памяти. например:

f = open('filename.txt') 
lines = f.readlines() 
num_lines = len(lines) 
last_line = lines[-1] 

Однако для больших файлов это может привести к увеличению объема памяти, так как весь файл загружается в ОЗУ. Альтернативой является итерация файла по строкам. например:

f = open('filename.txt') 
num_lines = sum(1 for line in f) 

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

f = open('filename.txt') 
count=0 
last_line = None 
for line in f: 
    num_lines += 1 
    last_line = line 
print "There were %d lines. The last was: %s" % (num_lines, last_line) 

Одно последнее возможное улучшение, если вам нужно только последнюю строку, чтобы начать в конце файла и искать назад, пока не найдете символ новой строки. Here's вопрос, который имеет некоторый код, делающий это. Если вам нужна и linecount, но, тем не менее, нет альтернативы, кроме как итерации по всем строкам в файле.

+0

как читает весь файл проще всего? ваше второе решение выглядит намного проще. – nosklo

+2

easy не означает быстрый или эффективный :-p – fortran

2

Я бы тоже добавил к другим решениям, что некоторые из них (те, кто ищет \n) не будут работать с файлами с окончанием строки в стиле 9-го уровня (только \r) и что они могут содержать дополнительный пробел в конце концов, потому что множество текстовых редакторов добавляет его по каким-то любопытным причинам, поэтому вы можете или не захотите добавить чек для него.

+0

правый. использование функции for не будет иметь этой проблемы, поскольку python readline() уже имеет дело с этим. – nosklo

+0

FYI - OS-X использует сингл '\ n' http://en.wikipedia.org/wiki/Newline – JimB

+0

Право, um, OS 9 и ниже. Я никогда не знал, что Apple изменила свое мнение, хорошо, что они сделали ~ –

0

Для первого вопроса там вы уже несколько хороших, я предложу @ одного Брайана как лучшая (самый вещей, символ конца строки доказательство памяти и эффективный):

f = open('filename.txt') 
num_lines = sum(1 for line in f) 

За секунду один, я люблю @ nosklo один, но изменен, чтобы быть более общими должна быть:

import os 
f = open('myfile') 
to = f.seek(0, os.SEEK_END) 
found = -1 
while found == -1 and to > 0: 
    fro = max(0, to-1024) 
    f.seek(fro) 
    chunk = f.read(to-fro) 
    found = chunk.rfind("\n") 
    to -= 1024 

if found != -1: 
    found += fro 

он seachs в кусках 1Кба от конца файла, пока он не найдет символ новой строки или заканчивает файл. В конце кода найден индекс последнего символа новой строки.