LambdaLabTM
Computer Science · Class 12 · Binary Files
Binary filesModes⏱️ 12 min read

The Binary Modes

There is no new table to learn. The six binary modes are the six you already know with the letter b added — and 'wb' empties a file exactly as 'w' does. What the b changes is what travels in and out.

1The same six, with a b

'rb'
read

The file must already exist.

'wb'
write

Creates the file — and empties it if it was there.

'ab'
append

Adds to the end. Nothing already saved is lost.

'rb+'
read and write

The file must exist. Writing overwrites from the pointer.

'wb+'
write and read

Empties the file first, then allows both.

'ab+'
append and read

Adds at the end, and lets you read as well.

Read the first letter, then the extras
r keeps the file and reads it, w empties it, a adds to the end. A + allows the other job as well. A b makes it binary. Three questions, six answers — exactly as with text files.

2What the b actually changes

Let's Recap!
Without b (text mode)With b (binary mode)
What travels in and outstr — stringsbytes
write() takesa stringbytes
Line endingstranslated for your OSleft exactly as they are
Used withwrite(), read(), readline()pickle.dump(), pickle.load()
Suits.txt .py .csv.dat and every other object file
You will hardly ever handle bytes yourself
This chapter never calls f.write() on a binary file. pickle.dump() makes the bytes and writes them, and pickle.load() reads them and rebuilds the object. Your side of it stays lists and dictionaries.

3What happens if you forget the b

There is no default binary mode. Leave the b off and Python opens the file as text, and then tries to read those bytes as characters:

forgot_the_b.py
f = open('save.dat', 'r')
print(f.read())
f.close()
Output
Traceback (most recent call last):
  File "forgot_the_b.py", line 2, in <module>
    print(f.read())
          ^^^^^^^^
  File "<frozen codecs>", line 322, in decode
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x80 in position 0: invalid start byte

The same mistake the other way round:

wrong_way_round.py
import pickle

f = open('oops.dat', 'w')
pickle.dump([1, 2], f)
f.close()
Output
Traceback (most recent call last):
  File "wrong_way_round.py", line 4, in <module>
    pickle.dump([1, 2], f)
TypeError: write() argument must be str, not bytes
Two error messages worth recognising
UnicodeDecodeError means you opened a binary file in text mode — Python tried to turn the bytes into letters and one of them was not a letter. TypeError: write() argument must be str, not bytes means the opposite: you gave bytes to a file opened for text. Both are one missing b.

And f.write() on a binary file wants bytes, not a string, which is the third version of the same complaint:

strings_are_not_bytes.py
f = open('oops.dat', 'wb')
f.write('hello')
Output
Traceback (most recent call last):
  File "strings_are_not_bytes.py", line 2, in <module>
    f.write('hello')
TypeError: a bytes-like object is required, not 'str'

4What a binary file actually holds

Read one with 'rb' and you can see the bytes. This is the file made by pickling {'player': 'Ravi', 'level': 3, 'points': 120}:

the_bytes.py
f = open('save.dat', 'rb')
data = f.read()
f.close()

print(data)
print(len(data), 'bytes')
Output
b'\x80\x04\x95*\x00\x00\x00\x00\x00\x00\x00}\x94(\x8c\x06player\x94\x8c\x04Ravi\x94\x8c\x05level\x94K\x03\x8c\x06points\x94Kxu.'
53 bytes
Tip
The b in front of the quotes says these are bytes, not a string. You can pick out player and Ravi in the middle — pickle does not hide your text — but the numbers and the structure are stored in a form only pickle understands. You never read a file this way in practice; pickle.load() does it for you.

5Closing a binary file

Exactly as before. f.close() empties the buffer onto the disk and releases the file, and everything the closing lesson said still holds — including that a program which writes and never closes can leave a file with nothing in it.

closing.py
import pickle

f = open('marks.dat', 'wb')
pickle.dump([78, 91, 65], f)
f.close()

And with works the same way too, closing the file at the end of the block:

with_binary.py
import pickle

with open('marks.dat', 'wb') as f:
    pickle.dump([78, 91, 65], f)

print('closed?', f.closed)
Output
closed? True

6Which mode for which job

'wb'
Create the file, or start it again from empty

The first program of the chapter. Careful — it wipes an existing file.

'rb'
Read the records, or search them

Nothing can be damaged in this mode, which is why it is the one to use unless you mean to write.

'ab'
Add today's records to the ones already saved

The mode real programs use most. A second run adds; it does not replace.

'rb+'
Change a record that is already in the file

Read and write through one handle. The update lesson shows why this one needs care.

7Recap

Six modes: rb, rb+, wb, wb+, ab, ab+

The text modes with a b. The letter still decides everything: r keeps, w erases, a adds.

b means bytes

No characters, no encoding, no line-ending translation.

There is no default binary mode

Leave the b off and the file is opened as text, whatever its name ends with.

UnicodeDecodeError

A binary file opened in text mode. Python tried to read bytes as letters.

TypeError about str and bytes

The two halves do not match: bytes into a text file, or a string into a binary one.

close() is unchanged

Same method, same reasons — and with works exactly as it does for text.

✍️ Now write these yourself
  1. 1

    Pickle a list into test.dat, then open the file in 'r' and read it.

    Hint · UnicodeDecodeError. The b is not optional.

  2. 2

    Open test.dat in 'rb' and print f.read().

    Hint · Bytes, starting with b'. Your text is visible inside them.

  3. 3

    Write two programs that pickle one list each into the same file — one using 'wb', one using 'ab'.

    Hint · Run each twice and see which file grows.

  4. 4

    Rewrite one of your programs with with open(...) and check f.closed afterwards.

    Hint · True. Binary files are closed by the block just like text ones.

Quick Check

Which mode creates a binary file, erasing it if it already exists?

Quick Check

What does the b in 'rb' change?

Quick Check

pickle.dump([1, 2], f) where f was opened in 'w'. What happens?

Quick Check

Which mode would you use to add more records to an existing binary file?