Python

Python File I/O: Baca Tulis File

Tutorial lengkap Python File I/O — open, read, write, CSV, JSON, pathlib, context manager, dan praktik terbaik untuk bekerja dengan berbagai format file

1. Pengenalan File I/O

File I/O (Input/Output) adalah kemampuan untuk membaca dan menulis data ke file. Ini adalah keterampilan fundamental dalam pemrograman — mulai dari menyimpan konfigurasi, membaca data CSV, log aplikasi, hingga berkomunikasi dengan sistem lain.

Python menyediakan fungsi built-in open() dan modul-modul seperti csv, json, dan pathlib untuk menangani berbagai jenis file.

Pipeline File I/O

Diagram: File I/O Pipeline di Python
ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│              FILE I/O PIPELINE                          │
│                                                         │
│  1. BUKA FILE                                           │
│     f = open("data.txt", "r")                           │
│         ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”                  │
│         │  File Descriptor           │                  │
│         │  Mode: r/w/a/rb/wb        │                  │
│         │  Encoding: utf-8/latin-1   │                  │
│         ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜                  │
│                      │                                  │
│  2. OPERASI          ā–¼                                  │
│     ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”                  │
│     │  read()      → baca semua      │                  │
│     │  readline()  → baca per baris  │                  │
│     │  readlines() → list of lines   │                  │
│     │  write()     → tulis string    │                  │
│     │  writelines()→ tulis list      │                  │
│     ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜                  │
│                      │                                  │
│  3. TUTUP FILE       ā–¼                                  │
│     f.close()                                           │
│     # Atau pakai: with open() as f:  (auto-close)      │
│                                                         │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜

Format File yang Didukung

Format Modul Penggunaan
Teks (.txt)Built-in open()Konfigurasi, log, catatan
CSV (.csv)csvData tabular, spreadsheet
JSON (.json)jsonAPI, konfigurasi, pertukaran data
XML (.xml)xml.etreeDokumen terstruktur, SOAP
Binary (.bin)Built-in + structGambar, audio, file terkompresi
Excel (.xlsx)openpyxlSpreadsheet Excel

2. Membaca File Teks

Python — Membaca File
# ===== Cara 1: read() — baca seluruh isi file =====
f = open("data.txt", "r", encoding="utf-8")
isi = f.read()
print(isi)
f.close()  # WAJIB ditutup!

# ===== Cara 2: read(n) — baca n karakter =====
f = open("data.txt", "r")
first_100 = f.read(100)  # 100 karakter pertama
print(first_100)
f.close()

# ===== Cara 3: readline() — baca per baris =====
f = open("data.txt", "r")
baris1 = f.readline()  # Baris pertama
baris2 = f.readline()  # Baris kedua
print(baris1.strip())  # strip() hapus \n di akhir
print(baris2.strip())
f.close()

# ===== Cara 4: readlines() — semua baris sebagai list =====
f = open("data.txt", "r")
semua_baris = f.readlines()  # ['baris1\n', 'baris2\n', ...]
for i, baris in enumerate(semua_baris, 1):
    print(f"Baris {i}: {baris.strip()}")
f.close()

# ===== Cara 5: Iterasi langsung (PALING EFISIEN) =====
with open("data.txt", "r", encoding="utf-8") as f:
    for baris in f:  # Memory-efficient untuk file besar
        print(baris.strip())

Encoding

Python — Encoding
# Selalu tentukan encoding untuk menghindari error
# Encoding umum:
# utf-8    → Standar universal, mendukung semua karakter (termasuk Indonesia)
# latin-1  → Western European
# ascii    → Hanya karakter ASCII dasar

# UTF-8 (direkomendasikan)
with open("data_indonesia.txt", "r", encoding="utf-8") as f:
    print(f.read())

# Jika encoding tidak diketahui, coba deteksi:
# pip install chardet
import chardet

with open("mystery_file.txt", "rb") as f:
    raw = f.read()
    result = chardet.detect(raw)
    print(result)  # {'encoding': 'utf-8', 'confidence': 0.99, ...}

# Decode dengan encoding yang terdeteksi
teks = raw.decode(result['encoding'])
print(teks)
Python — Menulis File
# ===== Mode "w" — Write (OVERWRITE / TIMPA isi lama!) =====
with open("output.txt", "w", encoding="utf-8") as f:
    f.write("Baris pertama\n")
    f.write("Baris kedua\n")
    f.write("Baris ketiga\n")

# ===== Mode "a" — Append (TAMBAH di akhir) =====
with open("log.txt", "a", encoding="utf-8") as f:
    from datetime import datetime
    f.write(f"[{datetime.now()}] Aplikasi dimulai\n")
    f.write(f"[{datetime.now()}] Koneksi database berhasil\n")

# ===== writelines() — tulis list of strings =====
baris = [
    "Nama: Budi Santoso\n",
    "Umur: 25\n",
    "Kota: Jakarta\n",
    "Hobi: Programming\n"
]
with open("profil.txt", "w", encoding="utf-8") as f:
    f.writelines(baris)

# ===== Menulis dengan print() ke file =====
with open("laporan.txt", "w", encoding="utf-8") as f:
    print("=== Laporan Penjualan ===", file=f)
    print(f"Total: Rp 15,000,000", file=f)
    print(f"Tanggal: 2024-06-26", file=f)
    # print() otomatis tambah newline

# ===== Penting: Beda "w" dan "a" =====
# "w" → HAPUS semua isi lama, tulis baru
# "a" → TAMBAH di akhir file, isi lama tetap ada
# āš ļø Salah pakai "w" bisa menghapus data penting!
āš ļø Hati-hati dengan Mode "w"!

Mode "w" akan menghapus seluruh isi file sebelum menulis. Jika Anda ingin menambah data ke file yang sudah ada, gunakan mode "a" (append). Selalu pastikan mode yang benar sebelum menulis!

4. Mode File

Mode Keterangan Membuat Baru? Timpa Isi?
"r"Read (baca)āŒ (error jika tidak ada)Tidak
"w"Write (tulis)āœ…Ya, hapus semua
"a"Append (tambah)āœ…Tidak, tambah di akhir
"x"Create (buat baru)āœ…Error jika sudah ada
"r+"Read + WriteāŒTidak (overwrite sebagian)
"w+"Write + Readāœ…Ya, hapus semua
"rb"Read BinaryāŒBinary mode
"wb"Write Binaryāœ…Ya, hapus semua (binary)
Python — Mode File
# Mode "x" — Create (error jika sudah ada)
try:
    with open("file_baru.txt", "x", encoding="utf-8") as f:
        f.write("Ini file baru!\n")
    print("File berhasil dibuat!")
except FileExistsError:
    print("File sudah ada! Tidak ditimpa.")

# Mode "r+" — Read + Write (posisi pointer bisa diatur)
with open("data.txt", "r+", encoding="utf-8") as f:
    isi = f.read()       # Baca semua
    f.write("\nBaris baru ditambahkan")  # Tulis di akhir

# Pointer position
with open("data.txt", "r", encoding="utf-8") as f:
    print(f.tell())      # Posisi pointer: 0
    f.read(10)
    print(f.tell())      # Posisi pointer: 10
    f.seek(0)            # Kembali ke awal
    print(f.tell())      # Posisi pointer: 0

5. Context Manager (with statement)

Context manager dengan with adalah cara terbaik untuk bekerja dengan file. File otomatis ditutup bahkan jika terjadi error di dalam blok.

Python — Context Manager
# āŒ TANPA context manager — rawan resource leak
f = open("data.txt", "r")
try:
    data = f.read()
    # Jika error di sini, file tidak tertutup!
    proses(data)
finally:
    f.close()  # Harus manual

# āœ… DENGAN context manager — auto-close, aman
with open("data.txt", "r", encoding="utf-8") as f:
    data = f.read()
    # Jika error sekalipun, file tetap ditutup otomatis!
    proses(data)
# f sudah tertutup di sini

# Multiple context manager sekaligus
with open("input.txt", "r") as src, open("output.txt", "w") as dst:
    for baris in src:
        dst.write(baris.upper())

# Context manager untuk resource lain
import sqlite3
with sqlite3.connect("db.sqlite") as conn:
    cursor = conn.execute("SELECT * FROM users")
    # Koneksi otomatis ditutup
šŸ’” Tips

Selalu gunakan with open() sebagai context manager. Ini memastikan file ditutup otomatis bahkan jika terjadi exception. Tidak perlu lagi menulis f.close() secara manual!

6. Bekerja dengan CSV

CSV (Comma-Separated Values) adalah format paling umum untuk pertukaran data tabular. Python menyediakan modul csv built-in untuk membaca dan menulis CSV.

Python — CSV
import csv

# ===== Membaca CSV =====
with open("karyawan.csv", "r", encoding="utf-8") as f:
    reader = csv.reader(f)
    header = next(reader)  # Baris pertama = header
    print(f"Kolom: {header}")

    for row in reader:
        print(row)  # Setiap row adalah list

# ===== Membaca CSV sebagai Dictionary =====
with open("karyawan.csv", "r", encoding="utf-8") as f:
    reader = csv.DictReader(f)
    for row in reader:
        print(f"Nama: {row['Nama']}, Kota: {row['Kota']}")
        # Akses dengan nama kolom, bukan index

# ===== Menulis CSV =====
data = [
    ["Nama", "Umur", "Kota"],
    ["Budi", 25, "Jakarta"],
    ["Ani", 22, "Bandung"],
    ["Dimas", 28, "Surabaya"]
]

with open("output.csv", "w", newline="", encoding="utf-8") as f:
    writer = csv.writer(f)
    writer.writerows(data)
    # āš ļø newline="" mencegah baris kosong ekstra di Windows

# ===== Menulis CSV dengan DictWriter =====
header = ["Nama", "Umur", "Kota"]
rows = [
    {"Nama": "Budi", "Umur": 25, "Kota": "Jakarta"},
    {"Nama": "Ani", "Umur": 22, "Kota": "Bandung"},
]

with open("output_dict.csv", "w", newline="", encoding="utf-8") as f:
    writer = csv.DictWriter(f, fieldnames=header)
    writer.writeheader()
    writer.writerows(rows)

# ===== CSV dengan delimiter berbeda (TSV, semicolon) =====
with open("data.tsv", "r", encoding="utf-8") as f:
    reader = csv.reader(f, delimiter="\t")  # Tab-separated
    for row in reader:
        print(row)

with open("data_semicolon.csv", "r", encoding="utf-8") as f:
    reader = csv.reader(f, delimiter=";")  # Semicolon-separated
    for row in reader:
        print(row)

7. Bekerja dengan JSON

JSON (JavaScript Object Notation) adalah format pertukaran data yang paling populer — digunakan oleh API, konfigurasi, dan database NoSQL. Modul json di Python sangat mudah digunakan.

Python — JSON
import json

# ===== Python → JSON (Serialization) =====
data = {
    "nama": "Budi Santoso",
    "umur": 25,
    "kota": "Jakarta",
    "hobi": ["coding", "gaming", "reading"],
    "aktif": True,
    "ipk": None
}

# dumps() — Python dict → JSON string
json_string = json.dumps(data, indent=2, ensure_ascii=False)
print(json_string)
# {
#   "nama": "Budi Santoso",
#   "umur": 25,
#   ...
# }

# dump() — Python dict → tulis langsung ke file
with open("data.json", "w", encoding="utf-8") as f:
    json.dump(data, f, indent=2, ensure_ascii=False)
    # ensure_ascii=False agar karakter Indonesia tersimpan benar

# ===== JSON → Python (Deserialization) =====
# loads() — JSON string → Python dict
obj = json.loads(json_string)
print(obj["nama"])    # Budi Santoso
print(type(obj))      # <class 'dict'>

# load() — baca file JSON → Python dict
with open("data.json", "r", encoding="utf-8") as f:
    data = json.load(f)
    print(data)

# ===== Konversi tipe data =====
# JSON → Python:
# object  → dict
# array   → list
# string  → str
# number  → int/float
# true    → True
# false   → False
# null    → None

# ===== Contoh: Konfigurasi aplikasi =====
config = {
    "app_name": "BeebaneApp",
    "version": "2.0.0",
    "database": {
        "host": "localhost",
        "port": 5432,
        "name": "beebane_db"
    },
    "features": ["auth", "dashboard", "api"],
    "debug": False
}

# Simpan config
with open("config.json", "w", encoding="utf-8") as f:
    json.dump(config, f, indent=4, ensure_ascii=False)

# Baca config
with open("config.json", "r", encoding="utf-8") as f:
    app_config = json.load(f)
    print(f"Aplikasi: {app_config['app_name']}")
    print(f"DB Host: {app_config['database']['host']}")

8. Pathlib — Modern Path Handling

pathlib adalah modul modern (Python 3.4+) untuk menangani path file dan direktori dengan cara yang lebih intuitif dan cross-platform dibanding modul os.path.

Python — Pathlib
from pathlib import Path

# Membuat Path object
p = Path("data/latihan/file.txt")
print(p)           # data/latihan/file.txt
print(p.name)      # file.txt
print(p.stem)      # file (tanpa ekstensi)
print(p.suffix)    # .txt
print(p.parent)    # data/latihan
print(p.absolute()) # Path absolut lengkap

# Path khusus
home = Path.home()     # /home/user atau C:\Users\user
cwd = Path.cwd()       # Direktori kerja saat ini

# ===== Membuat direktori =====
Path("output/laporan").mkdir(parents=True, exist_ok=True)
# parents=True  → buat parent juga jika belum ada
# exist_ok=True → tidak error jika sudah ada

# ===== Mengecek keberadaan =====
p = Path("data.txt")
print(p.exists())      # True/False
print(p.is_file())     # True jika file
print(p.is_dir())      # True jika direktori

# ===== Membaca dan menulis dengan Pathlib =====
# Write text
Path("catatan.txt").write_text("Halo, ini catatan!\n", encoding="utf-8")

# Read text
isi = Path("catatan.txt").read_text(encoding="utf-8")
print(isi)

# Write JSON
import json
data = {"nama": "Budi", "umur": 25}
Path("data.json").write_text(json.dumps(data, indent=2), encoding="utf-8")

# Read JSON
data = json.loads(Path("data.json").read_text(encoding="utf-8"))

# ===== Iterasi isi direktori =====
# Semua file .py di direktori saat ini
for py_file in Path(".").glob("*.py"):
    print(f"Python file: {py_file.name}")

# Rekursif ke semua sub-direktori (**)
for py_file in Path(".").rglob("*.py"):
    print(f"Found: {py_file}")

# ===== Mengubah ekstensi =====
p = Path("data.csv")
json_path = p.with_suffix(".json")
print(json_path)  # data.json

# ===== Mengganti nama file =====
p = Path("old_name.txt")
p.rename("new_name.txt")

# ===== Menghapus file =====
p = Path("temporary.txt")
p.unlink()  # Hapus file (error jika tidak ada)
# p.unlink(missing_ok=True)  # Tidak error jika tidak ada

9. Modul os dan shutil

Python — os dan shutil
import os
import shutil

# ===== Informasi file =====
print(os.path.exists("data.txt"))     # True/False
print(os.path.getsize("data.txt"))    # Ukuran dalam bytes
print(os.path.abspath("data.txt"))    # Path absolut
print(os.path.dirname("/a/b/c.txt"))  # /a/b
print(os.path.basename("/a/b/c.txt")) # c.txt
print(os.path.splitext("file.txt"))   # ('file', '.txt')

# ===== Direktori =====
print(os.getcwd())                     # Direktori kerja saat ini
os.listdir(".")                         # Isi direktori (list)

# Buat direktori
os.makedirs("output/data/2024", exist_ok=True)

# ===== Operasi file =====
os.rename("old.txt", "new.txt")        # Ganti nama
os.remove("file.txt")                   # Hapus file
os.rmdir("empty_dir")                   # Hapus direktori kosong
shutil.rmtree("dir_with_contents")      # Hapus direktori + isinya!

# ===== Copy dan Move =====
shutil.copy("source.txt", "dest.txt")         # Copy file
shutil.copy2("source.txt", "dest.txt")        # Copy + metadata
shutil.copytree("src_dir", "dst_dir")         # Copy direktori
shutil.move("file.txt", "archive/file.txt")   # Pindahkan

# ===== Walking directory tree =====
for root, dirs, files in os.walk("project"):
    for file in files:
        filepath = os.path.join(root, file)
        print(filepath)

# ===== Environment variables =====
print(os.environ.get("HOME"))          # Home directory
print(os.environ.get("PATH"))          # PATH system

10. File Binary

Python — Binary File
# ===== Copy file binary (gambar, PDF, dll) =====
with open("foto_asli.jpg", "rb") as src:
    with open("foto_copy.jpg", "wb") as dst:
        chunk_size = 4096  # Baca 4KB sekaligus
        while True:
            chunk = src.read(chunk_size)
            if not chunk:
                break
            dst.write(chunk)

# ===== Lebih ringkas dengan shutil =====
import shutil
shutil.copy("foto_asli.jpg", "foto_copy.jpg")

# ===== Membaca dan menulis bytes =====
# Tulis bytes
with open("data.bin", "wb") as f:
    f.write(b'\x00\x01\x02\x03')
    f.write(bytes([10, 20, 30, 40]))

# Baca bytes
with open("data.bin", "rb") as f:
    raw = f.read()
    print(raw)        # b'\x00\x01\x02\x03\x0a\x14\x1e\x28'
    print(list(raw))  # [0, 1, 2, 3, 10, 20, 30, 40]

# ===== Base64 encoding =====
import base64

# Encode bytes ke base64 string
with open("image.png", "rb") as f:
    encoded = base64.b64encode(f.read()).decode("utf-8")
    print(f"Base64: {encoded[:50]}...")

# Decode base64 kembali ke bytes
decoded_bytes = base64.b64decode(encoded)
with open("image_restored.png", "wb") as f:
    f.write(decoded_bytes)

11. Proyek Praktik: Sistem Catatan Harian

Gabungkan semua yang telah dipelajari dalam proyek mini — sistem catatan harian dengan format JSON:

Python — Catatan Harian
import json
from datetime import datetime
from pathlib import Path

FILE_NOTES = Path("catatan_harian.json")

def load_notes():
    """Baca catatan dari file JSON."""
    if not FILE_NOTES.exists():
        return []
    return json.loads(FILE_NOTES.read_text(encoding="utf-8"))

def save_notes(notes):
    """Simpan catatan ke file JSON."""
    FILE_NOTES.write_text(
        json.dumps(notes, indent=2, ensure_ascii=False),
        encoding="utf-8"
    )

def tambah_catatan(judul, isi):
    """Tambah catatan baru."""
    notes = load_notes()
    notes.append({
        "id": len(notes) + 1,
        "tanggal": datetime.now().strftime("%Y-%m-%d %H:%M"),
        "judul": judul,
        "isi": isi
    })
    save_notes(notes)
    print(f"āœ… Catatan '{judul}' berhasil ditambahkan!")

def cari_catatan(keyword):
    """Cari catatan berdasarkan keyword."""
    notes = load_notes()
    hasil = [n for n in notes if keyword.lower() in n["judul"].lower()
             or keyword.lower() in n["isi"].lower()]
    return hasil

def tampilkan_semua():
    """Tampilkan semua catatan."""
    notes = load_notes()
    if not notes:
        print("šŸ“­ Belum ada catatan.")
        return
    print(f"\nšŸ““ Daftar Catatan ({len(notes)} entri):\n")
    for note in notes:
        print(f"  [{note['tanggal']}] {note['judul']}")
        print(f"    {note['isi']}")
        print()

def export_ke_txt():
    """Export semua catatan ke file TXT."""
    notes = load_notes()
    with open("catatan_export.txt", "w", encoding="utf-8") as f:
        f.write("=" * 50 + "\n")
        f.write("EXPORT CATATAN HARIAN\n")
        f.write(f"Tanggal export: {datetime.now()}\n")
        f.write("=" * 50 + "\n\n")
        for note in notes:
            f.write(f"[{note['tanggal']}] {note['judul']}\n")
            f.write(f"  {note['isi']}\n\n")
    print(f"āœ… {len(notes)} catatan berhasil di-export ke catatan_export.txt")

# Contoh penggunaan
tambah_catatan("Belajar Python", "Hari ini belajar File I/O")
tambah_catatan("Meeting Tim", "Diskusi roadmap Q3 2024")
tambah_catatan("Ide Proyek", "Buat app pengelolaan keuangan sederhana")
tampilkan_semua()
export_ke_txt()

12. Quiz: Uji Pemahamanmu!

Setelah membaca tutorial di atas, jawablah 5 pertanyaan berikut untuk menguji pemahamanmu tentang Python File I/O:

Pertanyaan 1: Apa perbedaan mode "w" dan "a" saat membuka file?

a) "w" untuk Windows, "a" untuk Apple
b) "w" menimpa isi file, "a" menambah di akhir
c) "w" untuk write binary, "a" untuk write ASCII
d) Tidak ada perbedaan

Pertanyaan 2: Mengapa disarankan menggunakan with open() daripada open() langsung?

a) Lebih cepat secara performa
b) File otomatis ditutup meskipun terjadi error
c) Bisa membaca file yang lebih besar
d) Tidak perlu menentukan mode file

Pertanyaan 3: Fungsi apa yang digunakan untuk mengonversi Python dict ke JSON string?

a) json.load()
b) json.loads()
c) json.dump()
d) json.dumps()

Pertanyaan 4: Apa output dari Path("/home/user/data.csv").suffix?

a) "data.csv"
b) "data"
c) ".csv"
d) "/home/user/"

Pertanyaan 5: Parameter apa yang penting saat menulis CSV di Windows untuk mencegah baris kosong?

a) encoding="utf-8"
b) newline=""
c) delimiter=","
d) quotechar='"'
šŸ” Zoom
100%
šŸŽØ Tema