Data di dunia nyata umumnya tersimpan sebagai baris-baris teks: daftar nama, log aplikasi, hasil ekspor. Python menyediakan empat cara membaca berkas teks — read(), readline(), readlines(), dan iterasi langsung — dan masing-masing punya waktu terbaiknya. Memilih yang salah pada berkas berukuran besar bisa membuat program lambat atau kehabisan memori, jadi chapter ini juga menunjukkan pilihan yang aman untuk kondisi ekstrem.

Sebagai bahan uji sepanjang chapter, kita siapkan satu berkas kecil:

python
with open("siswa.txt", "w", encoding="utf-8") as berkas:
    berkas.write("Budi Santoso\nSiti Nurhaliza\nJoko Anwar\n")

Isi berkas siswa.txt:

text
Budi Santoso
Siti Nurhaliza
Joko Anwar

read() — Seluruh Isi Sekaligus #

Tanpa argument, method read() mengambil seluruh isi berkas sebagai satu string:

python
with open("siswa.txt", encoding="utf-8") as berkas:
    isi = berkas.read()

print(repr(isi))
print("Jumlah karakter:", len(isi))

Output yang Dihasilkan:

text
'Budi Santoso\nSiti Nurhaliza\nJoko Anwar\n'
Jumlah karakter: 39

Perhatikan dua hal dari output tersebut:

  1. Baris repr: karakter \n di akhir setiap baris ikut terbaca — read() tidak pernah membuang penanda akhir baris, sehingga rstrip("\n") atau splitlines() biasanya menyusul.
  2. len(isi) bernilai 39: 36 huruf plus 3 karakter \n.

Method read() juga menerima argument jumlah karakter untuk mengambil sebagian isi:

python
with open("siswa.txt", encoding="utf-8") as berkas:
    potongan = berkas.read(4)
    print(repr(potongan))
    lanjutan = berkas.read(4)
    print(repr(lanjutan))
    sisanya = berkas.read()
    print(repr(sisanya))

Output yang Dihasilkan:

text
'Budi'
' San'
'toso\nSiti Nurhaliza\nJoko Anwar\n'

Setiap pemanggilan read() melanjutkan dari posisi baca terakhir, bukan dari awal berkas.

readline() dan readlines() #

Method readline() mengambil satu baris sekaligus, lengkap dengan karakter \n-nya:

python
with open("siswa.txt", encoding="utf-8") as berkas:
    baris1 = berkas.readline()
    baris2 = berkas.readline()
    baris3 = berkas.readline()
    baris4 = berkas.readline()

print(repr(baris1))
print(repr(baris2))
print(repr(baris3))
print(repr(baris4))

Output yang Dihasilkan:

text
'Budi Santoso\n'
'Siti Nurhaliza\n'
'Joko Anwar\n'
''

Pemanggilan keempat mengembalikan string kosong '' — inilah tanda akhir berkas (EOF). Bandingkan dengan baris kosong di tengah berkas yang mengembalikan '\n': string kosong '' hanya muncul saat posisi baca sudah tidak menyisakan apa pun.

Sementara itu, readlines() mengambil semua baris sekaligus sebagai list:

python
with open("siswa.txt", encoding="utf-8") as berkas:
    daftar = berkas.readlines()

print(daftar)
print("Jumlah baris:", len(daftar))

bersih = [b.rstrip("\n") for b in daftar]
print(bersih)

Output yang Dihasilkan:

text
['Budi Santoso\n', 'Siti Nurhaliza\n', 'Joko Anwar\n']
Jumlah baris: 3
['Budi Santoso', 'Siti Nurhaliza', 'Joko Anwar']

List comprehension membersihkan \n dari setiap elemen — materi lengkapnya ada pada section Comprehensions dan Iterators. Karena readlines() juga memuat semuanya ke memori, method ini cocok untuk berkas kecil yang memang butuh diperlakukan sebagai list.

Iterasi Baris demi Baris #

Object file adalah iterable: loop for memintanya satu baris setiap putaran, membaca secara malas (lazy) tanpa memuat seluruh berkas ke memori:

python
with open("siswa.txt", encoding="utf-8") as berkas:
    for nomor, baris in enumerate(berkas, start=1):
        print(f"Baris {nomor}: {baris.rstrip()}")

Output yang Dihasilkan:

text
Baris 1: Budi Santoso
Baris 2: Siti Nurhaliza
Baris 3: Joko Anwar

Mari kita bedah dua baris intinya:

  1. Baris 2 (for nomor, baris in enumerate(berkas, start=1):): loop for meminta object file satu baris per putaran — object file menyerahkan baris berikutnya dari posisi baca, bukan memuat semuanya di awal.
  2. Baris 3 (print(f"Baris {nomor}: {baris.rstrip()}")): f-string menyisipkan nomor dan isi baris; rstrip() membuang \n di ujung agar tidak muncul baris kosong di antara hasil.

Fungsi enumerate() dari section Comprehensions dan Iterators menambahkan nomor urut. Pola for baris in berkas: inilah yang sebaiknya menjadi default kita — kode tetap ringkas untuk berkas tiga baris dan tetap hemat untuk berkas tiga juta baris.

tell(), seek(), dan Berkas Kosong #

Setiap object file menyimpan posisi baca saat ini. Method tell() melaporkannya sebagai jumlah byte dari awal, dan seek() memindahkannya:

python
with open("siswa.txt", encoding="utf-8") as berkas:
    print("Posisi awal:", berkas.tell())
    baris1 = berkas.readline()
    print("Setelah baris pertama:", berkas.tell())
    berkas.seek(0)
    print("Setelah seek(0):", berkas.tell())
    print(repr(berkas.readline()))

Output yang Dihasilkan:

text
Posisi awal: 0
Setelah baris pertama: 13
Setelah seek(0): 0
'Budi Santoso\n'

Baris pertama 'Budi Santoso\n' panjangnya 13 karakter — semuanya ASCII sehingga 13 karakter sama dengan 13 byte. Setelah seek(0), pembacaan berikutnya mengulang dari awal, seperti dicetak pada baris terakhir output. Kombinasi tell()/seek() biasanya baru dibutuhkan pada format berkas berstruktur — misalnya membaca ulang header setelah data diproses — dan jarang muncul dalam pengolahan teks baris demi baris.

Terakhir, berkas kosong tidak error — semua cara membaca hanya mengembalikan nilai kosong:

python
open("kosong.txt", "w").close()

with open("kosong.txt", encoding="utf-8") as berkas:
    print("read():", repr(berkas.read()))
    berkas.seek(0)
    print("readlines():", berkas.readlines())
    berkas.seek(0)
    for baris in berkas:
        print("baris:", repr(baris))
print("Selesai: tidak ada baris yang dicetak")

Output yang Dihasilkan:

text
read(): ''
readlines(): []
Selesai: tidak ada baris yang dicetak

read() mengembalikan '', readlines() mengembalikan [], dan loop tidak mengeksekusi badannya sekali pun. Program kita tinggal memeriksa hasil kosong tersebut bila berkas kosong adalah kondisi yang perlu ditangani.