2013-04-28 16 views
11

Mam plik, w którym wiersze są rozdzielane przy użyciu ogranicznika powiedz: .. Chcę czytać ten plik wiersz po wierszu, gdzie linie powinny być oparte na obecności . zamiast linii nowej.Odczytywanie pliku z określonym separatorem dla nowej linii

Jednym ze sposobów jest:

f = open('file','r') 
for line in f.read().strip().split('.'): 
    #....do some work 
f.close() 

Ale to nie jest pamięć wydajny jeśli mój plik jest zbyt duży. Zamiast czytać cały plik razem, chcę go czytać wiersz po wierszu.

open obsługuje parametr "nowa linia", ale ten parametr przyjmuje tylko None, '', '\n', '\r', and '\r\n' jako dane wejściowe, jak wspomniano here.

Czy istnieje sposób na wydajne odczytanie linii plików, ale na podstawie wcześniej określonego ogranicznika?

Odpowiedz

17

Można użyć generatora:

def myreadlines(f, newline): 
    buf = "" 
    while True: 
    while newline in buf: 
     pos = buf.index(newline) 
     yield buf[:pos] 
     buf = buf[pos + len(newline):] 
    chunk = f.read(4096) 
    if not chunk: 
     yield buf 
     break 
    buf += chunk 

with open('file') as f: 
    for line in myreadlines(f, "."): 
    print line 
+0

Kudos @NPE! Prosty i działa jak urok. –

+0

Można nieco uprościć, zmieniając początek zewnętrznej pętli na 'for chunk in iter (functools.partial (f.read, 4096), ''): buf + = chunk' i dodając' if buf: yield buf' po pętli (nie w środku). – Harvey

2

Najprostszym sposobem byłoby Preprocesuj plik wygenerować nowe linie gdzie chcesz.

Oto przykład przy użyciu Perl (zakładając, że chcesz ciąg „abc”, aby być przełamane):

perl -pe 's/abc/\n/g' text.txt > processed_text.txt 

Jeśli chcesz także ignorować oryginalne znaki nowej linii, należy stosować następujące zamiast:

perl -ne 's/\n//; s/abc/\n/g; print' text.txt > processed_text.txt