file handling
reading and writing
programming
coding tutorial
file operations

How to open a file for both reading and writing?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Opening a file for both reading and writing means choosing a mode that allows the program to inspect existing content and then modify the same file handle. In Python, the main modes for this are r+, w+, and a+, and the important difference between them is what happens to the file when you open it.

Choose the Right File Mode

The three most useful read-write modes are:

  • 'r+ for reading and writing without truncating'
  • 'w+ for reading and writing after truncating the file'
  • 'a+ for reading and appending'

They are similar enough to be confusing, so the file-opening decision should happen before you write any code that touches the file contents.

Use r+ When the File Must Already Exist

r+ opens a file for both reading and writing, but it does not create the file. It also keeps the existing contents.

python
1from pathlib import Path
2
3path = Path("notes.txt")
4
5with path.open("r+", encoding="utf-8") as file:
6    original = file.read()
7    file.seek(0)
8    file.write(original.upper())
9    file.truncate()

This example reads the entire file, moves the file pointer back to the beginning with seek(0), writes updated content, and then truncates the file so old leftover bytes do not remain at the end.

That last step matters whenever the new content may be shorter than the original.

Use w+ When You Want a Fresh File

w+ is more destructive. It opens the file for reading and writing, creates it if needed, and truncates it immediately.

python
1from pathlib import Path
2
3path = Path("report.txt")
4
5with path.open("w+", encoding="utf-8") as file:
6    file.write("first line\n")
7    file.seek(0)
8    print(file.read())

This mode is correct when you intentionally want to replace the entire file. It is the wrong choice if you needed the old data, because that data is erased as soon as the file opens.

Use a+ for Read and Append Workflows

a+ keeps existing content and creates the file if it does not exist, but writes always go to the end of the file.

python
1from pathlib import Path
2
3path = Path("events.log")
4
5with path.open("a+", encoding="utf-8") as file:
6    file.write("new event\n")
7    file.seek(0)
8    print(file.read())

This is useful for log-like files or journals where updates should be appended rather than inserted in the middle.

File Pointer Position Is a Big Part of the Problem

Many read-write bugs are really pointer-position bugs. After a read(), the pointer is at the end of the file. After a write() in append mode, it is still effectively treated as an append position for later writes.

That is why seek() shows up so often in correct examples. If you want to read again from the start, call file.seek(0). If you want to overwrite a specific region, move the pointer first.

Binary Variants Work the Same Way

If the file contains bytes rather than text, add b to the mode:

  • 'rb+'
  • 'wb+'
  • 'ab+'

The semantics stay the same, but the file object reads and writes bytes instead of strings.

Common Pitfalls

The biggest pitfall is using w+ when you meant r+. w+ truncates the file immediately, so the original contents are gone before your logic even runs.

Another common issue is forgetting seek(0) before rereading or overwriting. The file pointer does not reset automatically.

People also forget truncate() after rewriting shorter content. Without it, stale bytes from the original file may remain at the end.

Finally, remember that r+ requires the file to exist already. If you want a mode that creates the file when missing, use w+ or a+ depending on the intended behavior.

Summary

  • Use r+ to read and write without truncating an existing file.
  • Use w+ to start fresh, knowing that it erases old contents immediately.
  • Use a+ when you need to read the file and append new data to the end.
  • Manage the file pointer explicitly with seek() during mixed read-write workflows.
  • Call truncate() after overwriting shorter content so stale bytes are removed.

Course illustration
Course illustration