2010-06-12 13 views
8

Piszę program listy zadań. Utrzymuje plik z rzeczą do zrobienia na linię i pozwala użytkownikowi dodawać lub usuwać przedmioty. Problem polega na tym, że z jakiegoś powodu na początku pliku kończę z dużą ilością zerowych bajtów, mimo że przedmiot został poprawnie usunięty. Pokażę ci kilka zrzutów ekranu, żeby się upewnić.Zapisywanie do pliku w Pythonie wstawia bajty null

Jest to plik w Notepad ++ przed uruchomieniem programu:

Normal todo list http://img683.imageshack.us/img683/2812/beforew.png

Jest to plik po usunięciu pkt 3 (licząc od 1):

Item 3 is gone, but there are NUL bytes http://img190.imageshack.us/img190/9387/afterj.png

Jest to odpowiedni kod. Rzeczywisty program jest większy, ale uruchomienie tylko tej części powoduje błąd.

import os 
TODO_FILE = r"E:\javi\code\Python\todo-list\src\todo.txt" 

def del_elems(f, delete): 
    """Takes an open file and either a number or a list of numbers, and deletes the 
    lines corresponding to those numbers (counting from 1).""" 
    if isinstance(delete, int): 
     delete = [delete] 
    lines = f.readlines() 
    f.truncate(0) 
    counter = 1 
    for line in lines: 
     if counter not in delete: 
      f.write(line) 
     counter += 1 

f = open(TODO_FILE, "r+") 
del_elems(f, 3) 
f.close() 

Czy możesz wskazać, gdzie jest błąd?

Odpowiedz

9

Wygląda na to, że zapominasz przewinąć swój strumień plików. Po f.truncate(0) dodaj f.seek(0). W przeciwnym razie, myślę, że twój następny zapis spróbuje zacząć od pozycji, z której przerwałeś, wypełniając po drodze puste bajty.

(Zauważ, że liczba znaków zerowych W przykładzie jest równa liczbie znaków w usuniętych linii plus wózek zwrotny i line-feed znaków dla każdego z nich).

6

Z Python manual:

file.truncate([size])
Skróć rozmiar pliku. Jeśli opcjonalny argument rozmiar jest obecny, plik jest obcinany do (najwyżej) tego rozmiaru. Rozmiar domyślnie przyjmuje aktualną pozycję. Aktualna pozycja pliku nie jest zmieniana. Należy zauważyć, że jeśli określony rozmiar przekracza bieżący rozmiar pliku, wynik jest zależny od platformy: możliwości obejmują to, że plik może pozostać niezmieniony, zwiększyć do określonego rozmiaru, jak gdyby był wypełniony zero, lub zwiększyć do określonego rozmiaru z niezdefiniowaną nową treścią . Dostępność: Windows, wiele wariantów Uniksa.

Skracasz plik, a następnie zapisujesz item1 i item2 na poprzednim końcu pliku. Wszystko przedtem kończy się dopełnieniem 0 bajtów.

f.seek(0) 

Zadzwoń, aby zresetować położenie pliku po obcięciu.

+0

Wielkie dzięki. Twoja odpowiedź była tak dobra, jak Forest, ale musiałem wybrać jedną, aby zaakceptować, więc wybrałem wcześniejszą. Nic osobistego. – Javier

3

Weź podpowiedź. Nie rób tego.

W dawnych czasach (30 lat temu - na poważnie) "zaktualizowaliśmy" pliki za pomocą złożonej logiki dodawania/zmiany/usuwania.

W dzisiejszych czasach życie jest prostsze, jeśli piszesz programy

  1. odczytać cały plik do pamięci.

  2. Praca z obiektami w pamięci.

  3. Zapisuj obiekty do pliku okresowo i kiedy użytkownik chce zapisać.

Jest szybszy i prostszy. Użyj opcji pickle, aby zrzucić obiekty do pliku. Nie zadzieraj z "rekordami" lub próbą zmiany pliku "na miejscu".

Jeśli naprawdę sądzisz, że potrzebujesz funkcji SQL (Insert, Update, Delete), użyj SQLite. Jest bardziej niezawodny niż to, co próbujesz zrobić.

+1

To było dla praktyki, ale jest to interesujący punkt. Zobaczę, czy zmienię to tak, by zachowywało się tak, jak mówisz. – Javier