在Python中写入文件插入了空字节

9 投票
3 回答
4669 浏览
提问于 2025-04-15 23:53

我正在写一个待办事项程序。这个程序会把每一项待办事项写在文件的一行里,并允许用户添加或删除事项。问题是,不知道为什么,文件开头总是会出现很多零字节,尽管事项已经被正确删除了。我会给你看几张截图,以确保我说得清楚。

这是在运行程序之前,Notepad++中打开的文件:

正常的待办事项列表

这是删除第3项(从1开始计数)后的文件:

第3项已删除,但有NUL字节

这是相关的代码。实际程序更大,但运行这一部分就会出现错误。

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

你能指出错误在哪里吗?

3 个回答

3

听着,别这么做。

在很久以前(大约30年前——真的),我们更新文件时需要用复杂的添加、修改、删除逻辑。

现在生活简单多了,如果你写程序的话,建议这样做:

  1. 把整个文件读到内存里。

  2. 在内存中处理这些数据。

  3. 定期把数据写回文件,或者当用户想保存时再写。

这样做更快也更简单。可以用 pickle 把你的数据保存到文件里。别去搞什么“记录”或者试图直接在文件里修改。

如果你真的觉得需要SQL的功能(插入、更新、删除),那就用SQLite吧。它比你现在尝试的方式更可靠。

8

来自Python手册的内容:

file.truncate([size])
这个方法用来缩短文件的大小。如果你提供了一个可选的size参数,文件会被缩短到这个大小(最多到这个大小)。如果没有提供,默认会缩短到当前的位置。注意,当前文件的位置不会改变。另外,如果你指定的大小比文件现在的大小还大,结果可能会因平台而异:可能文件保持不变,可能会增加到指定的大小并用零填充,或者可能会增加到指定的大小但内容不确定。这个功能在Windows和许多Unix系统上都可以使用。

你在缩短文件后,会在文件原来的末尾写入item1和item2。这样之前的内容就会被填充为0字节。

f.seek(0)

在缩短文件后,调用这个方法可以重置文件的位置。

16

看起来你忘记了重置你的文件流。在 f.truncate(0) 之后,记得加上 f.seek(0)。否则,我觉得你下一次写入的时候会从你上次停止的位置开始,这样会在那个位置之前填充一些空字节。

(注意,你例子中的空字符数量等于你删除的行数加上每一行的回车和换行字符。)

撰写回答