2013-07-15 33 views
6

Moim celem jest odczytanie linii z pliku, usunięcie pustych miejsc na końcu i ponowne zapisanie w tym samym pliku. Próbowałem następujący kod:Powrót do tego samego pliku po przeczytaniu z pliku

with open(filename, 'r+') as f: 
    for i in f: 
     f.write(i.rstrip()+"\n") 

To wydaje się pisać na końcu pliku, zachowując początkowe dane w pliku nienaruszonym. Wiem, że użycie f.seek(0) spowodowałoby przeniesienie wskaźnika do początku pliku, co zakładam, że będzie w jakiś sposób wymagane dla tego rozwiązania.

Czy możesz doradzić, czy jest inne podejście do tego, czy jestem na właściwej poprawce, wystarczy dodać więcej logiki do kodu?

Odpowiedz

5

Użyj pliku tymczasowego. Python zapewnia urządzenia do tworzenia plików tymczasowych w bezpieczny sposób. przykład zadzwonić poniżej: python modify.py target_filename

import tempfile 
import sys 

def modify_file(filename): 

     #Create temporary file read/write 
     t = tempfile.NamedTemporaryFile(mode="r+") 

     #Open input file read-only 
     i = open(filename, 'r') 

     #Copy input file to temporary file, modifying as we go 
     for line in i: 
      t.write(line.rstrip()+"\n") 

     i.close() #Close input file 

     t.seek(0) #Rewind temporary file to beginning 

     o = open(filename, "w") #Reopen input file writable 

     #Overwriting original file with temporary file contents   
     for line in t: 
      o.write(line) 

     t.close() #Close temporary file, will cause it to be deleted 

if __name__ == "__main__": 
     modify_file(sys.argv[1]) 

Referencje tutaj: http://docs.python.org/2/library/tempfile.html

+0

Dobry przykład i świetne wyjaśnienie. – misguided

+0

Dzięki. Lubię korzystać z plików tymczasowych, nawet jeśli pamięć jest dostępna. Sprawdź również buforowany plik tymczasowy w dokumentach tempfile, co daje interesujący kompromis. – JonnyRo

1

Problem z twoim podejściem polega na tym, że potrzebujesz zarówno strumienia wejściowego, jak i wyjściowego, który może wskazywać w różnych miejscach tego samego pliku. Jeśli chcesz użyć f.seek(), musisz zapamiętać pozycję przy użyciu f.tell() po każdym odczycie i zapisaniu. Na przykład:

f = open(filename, 'r+') 
while True: 
    i = f.readline() 
    if i == '': break 
    in = f.tell() 
    f.seek(out) 
    f.write(i.rstrip()+"\n") 
    out = f.tell() 
    f.seek(in) 

Ale to jest mylące i podatne na błędy. Jeśli plik nie jest zbyt duży, dlaczego nie odczytać go w pamięci, a następnie zapisać ponownie?

in = open(filename, 'r') 
lines = in.read() 
in.close() 
out = open(filename, 'w') 
out.write([line.rstrip()+'\n' for line in lines.split('\n')]) 
out.close() 

Jeśli plik jest zbyt duży, aby zmieścić się w pamięci, a następnie napisać wiersze do pliku tymczasowego, a następnie zmień nazwę pliku, gdy skończysz:

out = open(filename+'.tmp', 'w') 
with open(filename, 'r') as f: 
    for i in f: 
     out.write(i.rstrip()+"\n") 
out.close() 
os.rename(filename+'.tmp', filename) 
+0

Twoja ostatnia rozwiązaniem wydaje się prawie rozwiązać ten problem, tylko kwestia pozostała istota, chcę nową nazwę pliku, aby zmienić tj. nowy plik powinien zastąpić stary plik. Jeśli zrobię to za pomocą metody określonej powyżej, otrzymam komunikat "WindowsError: [Błąd 183] Nie można utworzyć pliku, gdy ten plik już istnieje" – misguided

+1

To proste, po prostu usuń stary plik po jego zamknięciu, ale przed zmianą nazwy: 'os.remove (nazwa pliku) ' –