views:

57

answers:

3

I'm writing a todo list program. It keeps a file with a thing to do per line, and lets the user add or delete items. The problem is that for some reason, I end up with a lot of zero bytes at the start of the file, even though the item is correctly deleted. I'll show you a couple of screenshots to make sure I'm making myself clear.

This is the file in Notepad++ before running the program:

Normal todo list

This is the file after deleting item 3 (counting from 1):

Item 3 is gone, but there are NUL bytes

This is the relevant code. The actual program is bigger, but running just this part triggers the error.

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()

Could you please point out where's the mistake?

+6  A: 

It looks to me like you're forgetting to rewind your file stream. After f.truncate(0), add f.seek(0). Otherwise, I think your next write will try to start at the position from which you left off, filling in null bytes on its way there.

(Notice that the number of null characters in your example equals the number of characters in your deleted lines plus a carriage-return and line-feed character for each one.)

Forest
+3  A: 

From the Python manual:

file.truncate([size])
Truncate the file's size. If the optional size argument is present, the file is truncated to (at most) that size. The size defaults to the current position. The current file position is not changed. Note that if a specified size exceeds the file’s current size, the result is platform-dependent: possibilities include that the file may remain unchanged, increase to the specified size as if zero-filled, or increase to the specified size with undefined new content. Availability: Windows, many Unix variants.

You are truncating the file and then writing item1 and item2 at the former end of the file. Everything before that ends up padded with 0 bytes.

f.seek(0)

Call this to reset the file position after the truncate.

John Kugelman
Thanks a lot. Your answer was as good as Forest's, but I had to choose one to accept so I chose the earlier one. Nothing personal.
Javier Badia
+3  A: 

Take the hint. Don't do this.

In the olden days (30 years ago -- seriously) we "updated" files with complex add/change/delete logic.

Nowadays, life is simpler if you write programs that

  1. Read the entire file into memory.

  2. Work on the objects in memory.

  3. Write the objects to a file periodically and when the user wants to save.

It's faster and simpler. Use pickle to dump your objects to a file. Don't mess with "records" or any attempt to change a file "in place".

If you really think you need SQL capabilities (Insert, Update, Delete) then use SQLite. It's more reliable than what you're attempting to do.

S.Lott
This was for practice, but this is an interesting point. I'll see if I change it to behave like you say.
Javier Badia