2013-04-28 16 views
11

Ho un file in cui le righe sono separate utilizzando un delimitatore dire .. Voglio leggere questo file riga per riga, dove le linee dovrebbero essere basate sulla presenza di . invece di newline.Lettura di un file con un delimitatore specificato per newline

Un modo è:

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

Ma questo non è efficiente della memoria se il mio file è troppo grande. Invece di leggere un intero file insieme, voglio leggerlo riga per riga.

open supporta un parametro 'newline' ma questo parametro richiede solo None, '', '\n', '\r', and '\r\n' come input come indicato here.

C'è un modo per leggere la riga dei file in modo efficiente ma basato su un delimitatore pre-specificato?

risposta

17

si potrebbe usare un generatore:

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! Semplice e funziona come un fascino. –

+0

Potrebbe essere semplificato un po 'cambiando l'inizio del ciclo esterno a 'per chunk in iter (functools.partial (f.read, 4096),' '): buf + = chunk' e aggiungendo' if buf: yield buf' dopo il ciclo (non all'interno). – Harvey

2

Il modo più semplice sarebbe quella di pre-elaborazione del file per generare nuove righe in cui si desidera.

Ecco un esempio utilizzando Perl (supponendo che si desidera la stringa 'abc' essere il ritorno a capo):

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

Se anche voi volete ignorare le nuove linee originali, utilizzare il seguente invece:

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