Skip to main content
 首页 » 编程设计

python之如何使用二进制文件。覆盖特定字节

2025年05月04日13cmt

我正在用 python 编写程序,并希望能够写入二进制文件中的特定字节。我试图在 shell 中使用一个包含数字 0 到 15 的小二进制文件来执行此操作,但我不知道该怎么做。下面是我刚刚输入 shell 的代码,带有注释以演示我正在尝试做的事情:

>>> File=open("TEST","wb") # Opens the file for writing. 
>>> File.write(bytes(range(16))) # Writes the numbers 0 through 15 to the file. 
16 
>>> File.close() # Closes the file. 
>>> File=open("TEST","rb") # Opens the file for reading, so that we can test that its contents are correct. 
>>> tuple(File.read()) # Expected output: (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15) 
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15) 
>>> File.close() # Closes the file. 
>>> File=open("TEST","wb") # Opens the file for writing. 
>>> File.seek(3) # Moves the pointer to position 3. (Fourth byte.) 
3 
>>> File.write(b"\x01") # Writes 1 to the file in its current position. 
1 
>>> File.close() # Closes the file. 
>>> File=open("TEST","rb") # Opens the file for reading, so that we can test that its contents are correct. 
>>> tuple(File.read()) # Expected output: (0, 1, 2, 1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15) 
(0, 0, 0, 1) 
>>> File.close() 
>>> File=open("TEST","wb") # I will try again using apend mode to overwrite. 
>>> File.write(bytes(range(16))) 
16 
>>> File.close() 
>>> File=open("TEST","ab") # Append mode. 
>>> File.seek(3) 
3 
>>> File.write(b"\x01") 
1 
>>> File.close() 
>>> File=open("TEST","rb") 
>>> tuple(File.read()) # Expected output: (0, 1, 2, 1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15) 
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 1) 
>>> File.close() 

我想要的输出如图所示,但是 "wb" 似乎删除了文件中的所有数据,而 "ab" 无法向后查找。

如何在不重写整个文件的情况下实现我想要的输出?

请您参考如下方法:

当您使用 w 打开一个文件进行写入时,该文件将被截断,所有内容都会被删除。您需要使用 r+ 打开文件进行读写。来自 open() 函数文档:

'w' open for writing, truncating the file first

和

For binary read-write access, the mode 'w+b' opens and truncates the file to 0 bytes. 'r+b' opens the file without truncation.

因为文件先被截断,寻找位置 3 然后写入 \x01 前几个字节为您填充了 \x00。

以追加模式打开文件通常会限制对文件新部分的访问,因此超过前 16 个字节的任何内容。同样,来自文档:

Other common values are [...] and 'a' for appending (which on some Unix systems, means that all writes append to the end of the file regardless of the current seek position).

(在我引用的部分中大胆强调)。这就是为什么尽管调用了 File.seek(3),您的 \x01 字节还是在最后结束。

r 不会截断文件并使用 seek() 为您提供完整范围的内容; r+ 添加对该模式的写访问。使用 'r+b' 进行演示:

>>> with open('demo.bin', 'wb') as f: 
...     f.write(bytes(range(16))) 
... 
16 
>>> with open('demo.bin', 'rb') as f: 
...     print(*f.read()) 
... 
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 
>>> with open('demo.bin', 'r+b') as f:  # read and write mode 
...     f.seek(3) 
...     f.write(b'\x01') 
... 
3 
1 
>>> with open('demo.bin', 'rb') as f: 
...     print(*f.read()) 
... 
0 1 2 1 4 5 6 7 8 9 10 11 12 13 14 15