- What are binary files — understanding binary data
- Text vs binary — knowing the difference
- Reading binary files — working with non-text data
- Writing binary files — saving binary data
- struct module — working with packed data
- Real-world use — images and other files
What are Binary Files?
When we talk about binary files, we're talking about any file that isn't plain text. Your photos, music, videos, and even many documents are binary files. They contain data in a format that computers understand directly, but humans can't read without special software.
Think of it like this: text files are like a handwritten note you can read directly. Binary files are like a secret code — you need the right decoder to understand them. Python gives you the tools to work with both types.
💡 Key concept: Binary files store data as raw bytes. Unlike text files, they don't have a specific encoding or structure that's human-readable. They're used for images, audio, video, and other media.
Text Files vs Binary Files
Understanding the Difference
# Text files are human-readable, binary files are not
# 1. Creating a text file
with open("text_file.txt", "w") as f:
f.write("Hello, World!\n")
f.write("This is a text file.\n")
f.write("You can read this directly.\n")
# 2. Creating a binary file
with open("binary_file.bin", "wb") as f:
f.write(b"Hello, World!\n")
f.write(b"This is a binary file.\n")
f.write(b"You can't read this directly.\n")
# 3. Reading a text file
with open("text_file.txt", "r") as f:
content = f.read()
print("Text file content:")
print(content)
# 4. Reading a binary file (as text - will show bytes)
with open("binary_file.bin", "rb") as f:
content = f.read()
print("Binary file content (as bytes):")
print(content)
# 5. Key differences:
# Text files:
# - Use 'r' and 'w' modes
# - Work with strings
# - Human-readable
# - Have encoding (UTF-8, ASCII, etc.)
# Binary files:
# - Use 'rb' and 'wb' modes
# - Work with bytes
# - Not human-readable
# - No encoding (raw bytes)
Text vs Binary comparison:
- Text files — readable, work with strings, have encoding
- Binary files — not readable, work with bytes, no encoding
- Text modes — 'r', 'w', 'a'
- Binary modes — 'rb', 'wb', 'ab'
Quick Check: What mode is used to read a binary file? (Answer: 'rb')
Reading Binary Files
Working with Binary Data
# Reading binary files gives you bytes objects
# 1. Create a binary file
data = b"Hello, this is binary data!\n"
data += b"Here's some more bytes.\n"
data += bytes([65, 66, 67, 68, 69]) # ASCII values for A, B, C, D, E
with open("sample_binary.bin", "wb") as f:
f.write(data)
print("Created: sample_binary.bin")
# 2. Read the entire binary file
with open("sample_binary.bin", "rb") as f:
content = f.read()
print(f"Read {len(content)} bytes")
print(f"First 20 bytes: {content[:20]}")
# 3. Read in chunks (useful for large files)
with open("sample_binary.bin", "rb") as f:
chunk_size = 10
print("Reading in chunks:")
while True:
chunk = f.read(chunk_size)
if not chunk:
break
print(f" Chunk: {chunk}")
# 4. Read a specific number of bytes
with open("sample_binary.bin", "rb") as f:
first_5 = f.read(5)
print(f"First 5 bytes: {first_5}")
# 5. Convert bytes to readable form
with open("sample_binary.bin", "rb") as f:
content = f.read()
print("As text (where possible):")
print(content.decode('utf-8', errors='ignore'))
Reading binary files key points:
- Returns bytes — not strings, but bytes objects
- Can read all — f.read() for entire file
- Read in chunks — f.read(size) for large files
- No encoding issues — bytes are just raw data
Quick Check: What type of object does reading a binary file return? (Answer: bytes)
Writing Binary Files
Saving Binary Data
# Writing binary files requires bytes data
# 1. Writing bytes directly
with open("output.bin", "wb") as f:
f.write(b"This is binary data\n")
f.write(b"More binary data\n")
print("Created: output.bin")
# 2. Writing from a bytes object
data = bytes([10, 20, 30, 40, 50])
with open("numbers.bin", "wb") as f:
f.write(data)
print("Created: numbers.bin")
# 3. Writing from a bytearray
data = bytearray([100, 200, 150, 75, 25])
with open("bytearray.bin", "wb") as f:
f.write(data)
print("Created: bytearray.bin")
# 4. Converting strings to bytes for writing
text = "This is a string that becomes bytes"
with open("string_as_binary.bin", "wb") as f:
f.write(text.encode('utf-8'))
print("Created: string_as_binary.bin")
# 5. Writing multiple pieces
with open("combined.bin", "wb") as f:
f.write(b"Header\n")
f.write(bytes([1, 2, 3, 4]))
f.write(b"\nFooter\n")
print("Created: combined.bin")
# 6. Verify the written data
with open("combined.bin", "rb") as f:
content = f.read()
print(f"Combined file: {content}")
Writing binary files key points:
- Need bytes — strings must be encoded
- Use 'wb' mode — write binary
- Can write bytes — bytes(), bytearray(), b"..."
- Combine data — write multiple pieces
Quick Check: What mode is used to write a binary file? (Answer: 'wb')
Using the struct Module
Working with Packed Data
# The struct module helps work with binary data structures
import struct
# 1. Packing data (converting Python values to bytes)
# Format: 'i' = integer, 'f' = float, 'd' = double, 's' = string
# Pack an integer
packed_int = struct.pack('i', 42)
print(f"Integer 42 packed: {packed_int}")
# Pack a float
packed_float = struct.pack('f', 3.14)
print(f"Float 3.14 packed: {packed_float}")
# Pack multiple values
packed_data = struct.pack('i f d', 10, 20.5, 100.75)
print(f"Multiple values packed: {packed_data}")
# 2. Unpacking data (converting bytes back to Python values)
unpacked = struct.unpack('i f d', packed_data)
print(f"Unpacked: {unpacked}")
# 3. Packing strings (requires specifying length)
name = b"Alice"
packed_name = struct.pack('5s', name) # 5 characters
print(f"Packed name: {packed_name}")
# 4. Writing structured data to a file
def write_record(filename, id_number, score, name):
"""Write a record to a binary file"""
with open(filename, "ab") as f:
# Format: i=integer, f=float, 10s=string of 10 chars
packed = struct.pack('i f 10s', id_number, score, name.encode()[:10])
f.write(packed)
def read_records(filename):
"""Read all records from a binary file"""
records = []
with open(filename, "rb") as f:
record_size = struct.calcsize('i f 10s')
while True:
data = f.read(record_size)
if not data:
break
id_number, score, name = struct.unpack('i f 10s', data)
records.append({
'id': id_number,
'score': score,
'name': name.decode().strip('\x00')
})
return records
# 5. Test the record system
write_record("records.bin", 1, 95.5, "Alice")
write_record("records.bin", 2, 87.0, "Bob")
write_record("records.bin", 3, 92.3, "Charlie")
records = read_records("records.bin")
for record in records:
print(f"ID: {record['id']}, Score: {record['score']}, Name: {record['name']}")
# 6. Struct format codes
# 'c' - char (1 byte)
# 'b' - signed char (1 byte)
# 'B' - unsigned char (1 byte)
# 'h' - short (2 bytes)
# 'H' - unsigned short (2 bytes)
# 'i' - int (4 bytes)
# 'I' - unsigned int (4 bytes)
# 'f' - float (4 bytes)
# 'd' - double (8 bytes)
# 's' - string (variable)
struct module key points:
- Pack — convert Python values to bytes
- Unpack — convert bytes to Python values
- Format strings — define the structure
- Fixed size — great for records and files
Quick Check: What does struct.pack() do? (Answer: Converts Python values to bytes)
Working with Images
Real-World Binary Files
# Images are classic examples of binary files
# 1. Creating a simple image (PPM format - simple binary image)
def create_simple_image(filename, width=100, height=100):
"""Create a simple PPM image"""
# PPM header: P6 (binary), width, height, max color value
header = f"P6\n{width} {height}\n255\n"
# Create some pixel data (a gradient)
with open(filename, "wb") as f:
f.write(header.encode())
# Create a gradient from red to blue
for y in range(height):
for x in range(width):
r = 255 - (x * 255 // width)
g = 0
b = x * 255 // width
f.write(bytes([r, g, b]))
print("Creating simple image...")
create_simple_image("gradient.ppm")
print("Created: gradient.ppm")
# 2. Reading an image file and getting information
def get_image_info(filename):
"""Get basic info about an image file"""
with open(filename, "rb") as f:
# Try to detect if it's a PPM file
header = f.read(20)
if header.startswith(b"P6"):
print("This is a PPM image file")
# Find the width and height
lines = header.split()
width = int(lines[1])
height = int(lines[2])
print(f"Dimensions: {width} x {height}")
return
elif header.startswith(b'\x89PNG'):
print("This is a PNG file")
elif header.startswith(b'\xFF\xD8\xFF'):
print("This is a JPEG file")
elif header.startswith(b'GIF8'):
print("This is a GIF file")
else:
print(f"File type unknown. First bytes: {header[:10]}")
get_image_info("gradient.ppm")
# 3. Copying an image file (binary copy)
def copy_image(source, destination):
"""Copy an image file (or any binary file)"""
with open(source, "rb") as src:
data = src.read()
with open(destination, "wb") as dst:
dst.write(data)
print(f"Copied: {source} → {destination}")
copy_image("gradient.ppm", "gradient_copy.ppm")
# 4. Image file size information
def get_file_stats(filename):
"""Get statistics about a binary file"""
import os
size = os.path.getsize(filename)
print(f"File: {filename}")
print(f" Size: {size} bytes")
print(f" Size: {size / 1024:.2f} KB")
print(f" Size: {size / (1024 * 1024):.2f} MB")
get_file_stats("gradient.ppm")
# Note: For real image processing, use the Pillow library:
# from PIL import Image
# img = Image.open("image.jpg")
# img.show()
Image files key points:
- Different formats — PNG, JPEG, GIF, PPM
- Headers — contain format information
- Binary data — pixel data in various formats
- Specialized libraries — Pillow for real processing
Quick Check: Are images text or binary files? (Answer: Binary files)
Error Handling with Binary Files
Robust Binary File Operations
# Binary file operations need careful error handling
import os
# 1. Safe binary file read
def safe_read_binary(filename):
"""Safely read a binary file"""
try:
with open(filename, "rb") as f:
return f.read()
except FileNotFoundError:
print(f"File '{filename}' not found")
return None
except PermissionError:
print(f"Permission denied for '{filename}'")
return None
except Exception as e:
print(f"Error reading '{filename}': {e}")
return None
# 2. Safe binary file write
def safe_write_binary(filename, data):
"""Safely write a binary file"""
try:
with open(filename, "wb") as f:
f.write(data)
print(f"Successfully wrote '{filename}'")
return True
except PermissionError:
print(f"Permission denied for '{filename}'")
return False
except Exception as e:
print(f"Error writing '{filename}': {e}")
return False
# 3. Check if a file is binary or text
def is_binary_file(filename, sample_size=1024):
"""Guess if a file is binary or text"""
try:
with open(filename, "rb") as f:
sample = f.read(sample_size)
# Check for null bytes (common in binary files)
if b'\0' in sample:
return True
# Check for non-printable characters
text_chars = bytearray(range(32, 127)) + bytearray([9, 10, 13])
for byte in sample:
if byte not in text_chars:
return True
return False
except Exception:
return True # If we can't read it, assume binary
# 4. Safe file copy with verification
def safe_copy_binary(source, destination):
"""Copy a binary file and verify it"""
try:
# Read source
with open(source, "rb") as src:
data = src.read()
# Write destination
with open(destination, "wb") as dst:
dst.write(data)
# Verify
with open(destination, "rb") as dst:
copied_data = dst.read()
if data == copied_data:
print(f"Successfully copied and verified: {source} → {destination}")
return True
else:
print(f"Copy verification failed for {destination}")
return False
except Exception as e:
print(f"Error copying: {e}")
return False
Error handling key points:
- FileNotFoundError — file doesn't exist
- PermissionError — can't access the file
- Always use try-except — make your code robust
- Verify copies — ensure data integrity
Quick Check: Why should you verify binary file copies? (Answer: To ensure data integrity)
Best Practices for Binary Files
Professional Binary File Handling
# Best practices when working with binary files
# 1. Always use binary modes
# ✅ Good
with open("data.bin", "rb") as f:
data = f.read()
# ❌ Bad - might corrupt binary data
with open("data.bin", "r") as f:
data = f.read()
# 2. Use bytes objects consistently
# ✅ Good
data = b"Hello"
with open("output.bin", "wb") as f:
f.write(data)
# ❌ Bad - mixing types
data = "Hello"
with open("output.bin", "wb") as f:
f.write(data) # Error: must be bytes
# 3. Use struct for structured binary data
import struct
def write_structured_data(filename, records):
"""Write structured binary data"""
with open(filename, "wb") as f:
for record in records:
packed = struct.pack('i f 20s',
record['id'],
record['value'],
record['name'].encode()[:20])
f.write(packed)
# 4. Handle big files efficiently
def process_large_binary(filename):
"""Process a large binary file in chunks"""
chunk_size = 8192 # 8KB
with open(filename, "rb") as f:
while True:
chunk = f.read(chunk_size)
if not chunk:
break
# Process chunk
# (don't store the entire file in memory)
# 5. Document binary file formats
# When creating custom binary formats, document them:
#
# Record format:
# - id: 4 bytes (integer)
# - value: 4 bytes (float)
# - name: 20 bytes (string, padded with null bytes)
# Total record size: 28 bytes
# 6. Use appropriate libraries for complex formats
# For images: Pillow
# For audio: wave, pydub
# For video: OpenCV
# For scientific data: numpy
# 7. Test with sample files
# Always test binary file operations with small files first
Best practices summary:
- Use binary modes — 'rb' and 'wb'
- Use bytes — keep data in bytes format
- Use struct — for structured data
- Handle large files — read in chunks
- Document formats — explain your binary format
- Use libraries — for complex binary formats
Quick Check: What is the best way to read a large binary file? (Answer: Read it in chunks)
Try It Yourself
Experiment with binary files in the editor below. Try reading and writing binary data.
BINARY FILES PRACTICE
========================================
1. WRITING BINARY DATA
Created: binary_data.bin
2. READING BINARY DATA
Read 32 bytes
First 20 bytes: b'Hello, binary world!\n\n\x14\x1e('
3. USING STRUCT
Packed: b'*\x00\x00\x00\xc3\xf5H@\x9a\x99\x99\x99\x99\x99X@'
Unpacked: (42, 3.140000104904175, 99.99)
4. WRITING STRUCTURED RECORDS
Records written to records.bin
5. READING STRUCTURED RECORDS
ID: 1, Score: 95.5, Name: Alice
ID: 2, Score: 87.0, Name: Bob
Binary files practice complete!
You've Got It!
You now understand binary files in Python. You know how to read, write, and process binary data, including images and structured records.
Quick Quiz
Test what you've learned:
Frequently Asked Questions
What is the difference between text and binary files?
Can I convert a binary file to text?
What is the struct module used for?
struct module is used to convert between Python values and C-style binary data. It's essential for reading and writing binary file formats that have a specific structure, like database files, custom file formats, or network protocols.
What's a common interview question about binary files?
How do I know if a file is binary or text?
Can I use Python to process images?
Where to Go From Here
Now that you understand binary files, check out these related topics:
Zipping and Unzipping Files
Learn how to compress and extract files.
Learn More →📝 Assignments
Practice what you've learned with assignments.
Learn More →MySQL Database
Learn how to work with databases in Python.
Learn More →