Appending to binary files such as images, audio, or custom data formats requires different handling than text files. You must use the 'ab' (append binary) mode to add data without corrupting or overwriting the existing content.
This guide covers the essential techniques for working with binary file appending in Python.
Appending Raw Bytes
Use open(filename, 'ab') to open a file in append binary mode. The 'b' flag allows you to write bytes objects directly.
with open('data.bin', 'wb') as f:
f.write(b'\x01\x02\x03')
with open('data.bin', 'ab') as f:
f.write(b'\x04\x05')
f.write(b'\xFF\xFF')
with open('data.bin', 'rb') as f:
content = f.read()
print(content)Output:
b'\x01\x02\x03\x04\x05\xff\xff'Appending Integers with Data Packing
You cannot write integers directly to binary files. You must first convert numbers to bytes using the .to_bytes() method.
numbers = [500, 1000, 1500]
with open('numbers.dat', 'ab') as f:
for num in numbers:
bytes_data = num.to_bytes(4, byteorder='big')
f.write(bytes_data)Reading the Integers Back
with open('numbers.dat', 'rb') as f:
while True:
bytes_data = f.read(4)
if not bytes_data:
break
num = int.from_bytes(bytes_data, byteorder='big')
print(num)Output:
500
1000
1500Using the struct Module for Complex Data
For more complex binary formats, the struct module provides precise control over data packing.
import struct
data = struct.pack('>I f 4s', 42, 3.14, b'TEST')
with open('record.bin', 'ab') as f:
f.write(data)
with open('record.bin', 'rb') as f:
raw = f.read(struct.calcsize('>I f 4s'))
values = struct.unpack('>I f 4s', raw)
print(values)Output:
(42, 3.140000104904175, b'TEST')Appending One File to Another
To merge binary files, read the source in chunks to handle large files efficiently without loading everything into memory.
chunk_size = 4096 # Read in 4KB chunks
with open('source.bin', 'rb') as source:
with open('destination.bin', 'ab') as dest:
while True:
chunk = source.read(chunk_size)
if not chunk:
break
dest.write(chunk)Using shutil for Simpler Merging
For straightforward file copying, the shutil module provides a cleaner approach:
import shutil
with open('destination.bin', 'ab') as dest:
with open('source.bin', 'rb') as source:
shutil.copyfileobj(source, dest)Building a Simple Binary Logger
Here's a practical example that logs timestamped events to a binary file:
import struct
import time
def log_event(filename: str, event_code: int, value: float) -> None:
"""Append a timestamped event to a binary log file."""
timestamp = int(time.time())
record = struct.pack('>I H f', timestamp, event_code, value)
with open(filename, 'ab') as f:
f.write(record)
def read_events(filename: str) -> list:
"""Read all events from a binary log file."""
record_size = struct.calcsize('>I H f')
events = []
with open(filename, 'rb') as f:
while True:
data = f.read(record_size)
if not data:
break
timestamp, event_code, value = struct.unpack('>I H f', data)
events.append((timestamp, event_code, value))
return events
log_event('events.log', 1, 23.5)
log_event('events.log', 2, 47.8)
for event in read_events('events.log'):
print(event)Output:
(1770911190, 1, 23.5)
(1770911190, 2, 47.79999923706055)File Mode Reference
| Mode | Name | Behavior |
|---|---|---|
'wb' |
Write Binary | Overwrites existing file or creates new |
'ab' |
Append Binary | Adds to the end of existing file |
'rb' |
Read Binary | Reads binary data |
'r+b' |
Read/Write Binary | Read and write at any position |
Conclusions
- Use
'ab'mode to append binary data without overwriting existing content. - Convert integers to bytes using
.to_bytes()or thestructmodule. - Read large files in chunks to avoid memory issues.
- Never use text modes (
'a','w') for binary files, always include the'b'flag.