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:
This is the file after deleting item 3 (counting from 1):
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?
However, in Modified UTF-8 the null character is encoded as two bytes: 0xC0, 0x80. This allows the byte with the value of zero, which is now not used for any character, to be used as a string terminator.
Null Byte Injection is an active exploitation technique used to bypass sanity checking filters in web infrastructure by adding URL-encoded null byte characters (i.e. %00, or 0x00 in hex) to the user-supplied data.
Null is 00 in hexadecimal.
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.)
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.
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
Read the entire file into memory.
Work on the objects in memory.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With