我正在用 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
