C# menawarkan dua pendekatan untuk file I/O: File class dengan metode statis yang sederhana untuk operasi satu baris, dan StreamReader/StreamWriter untuk kontrol lebih detail. Keduanya bekerja dengan using statement (dari artikel exception handling) untuk memastikan resource selalu dibersihkan dengan benar.
File Class — Operasi Sederhana Satu Baris
using System.IO;
// Tulis semua teks (buat baru atau timpa yang ada)
File.WriteAllText("catatan.txt", "Halo, dunia!\nBaris kedua.");
// Tulis banyak baris
File.WriteAllLines("daftar.txt", new[] { "Apel", "Mangga", "Jeruk" });
// Baca semua teks sekaligus
string isi = File.ReadAllText("catatan.txt");
Console.WriteLine(isi);
// Output:
// Halo, dunia!
// Baris kedua.
// Baca sebagai array baris
string[] baris = File.ReadAllLines("daftar.txt");
foreach (string b in baris)
Console.WriteLine(b);
// Tambahkan teks di akhir (append)
File.AppendAllText("log.txt", $"[{DateTime.Now}] Aplikasi dijalankan\n");
// Cek keberadaan file
if (File.Exists("data.txt"))
Console.WriteLine("File ada!");
else
Console.WriteLine("File tidak ditemukan.");
// Salin, pindah, hapus
File.Copy("sumber.txt", "tujuan.txt", overwrite: true);
File.Move("lama.txt", "baru.txt");
File.Delete("temp.txt");
StreamReader dan StreamWriter — Kontrol Penuh
Gunakan stream untuk file besar (baca baris per baris tanpa load semua ke memori):
using System.IO;
// StreamWriter — tulis ke file
using (var writer = new StreamWriter("laporan.txt"))
{
writer.WriteLine("=== Laporan Penjualan ===");
writer.WriteLine($"Tanggal: {DateTime.Now:yyyy-MM-dd}");
writer.WriteLine();
var produk = new[] {
("Laptop", 15_000_000, 3),
("Mouse", 250_000, 10),
("Keyboard", 750_000, 7)
};
foreach (var (nama, harga, qty) in produk)
{
writer.WriteLine($"{nama,-15} Rp {harga,10:N0} x{qty} = Rp {harga * qty:N0}");
}
}
// StreamReader — baca file besar baris per baris
using (var reader = new StreamReader("laporan.txt"))
{
string? baris;
int nomor = 1;
while ((baris = reader.ReadLine()) != null)
{
Console.WriteLine($"{nomor++,3}: {baris}");
}
}
Path — Manipulasi Jalur File dengan Aman
using System.IO;
// Path.Combine — gabung path lintas platform (/ di Linux, \ di Windows)
string folder = Path.Combine("data", "pengguna");
string file = Path.Combine(folder, "profil.json");
Console.WriteLine(file);
// Windows: data\pengguna\profil.json
// Linux: data/pengguna/profil.json
// Komponen path
string fullPath = @"C:\Proyek\src\program.cs";
Console.WriteLine(Path.GetFileName(fullPath)); // program.cs
Console.WriteLine(Path.GetFileNameWithoutExtension(fullPath)); // program
Console.WriteLine(Path.GetExtension(fullPath)); // .cs
Console.WriteLine(Path.GetDirectoryName(fullPath)); // C:\Proyek\src
// Path sementara dan khusus
string temp = Path.GetTempFileName(); // File temp di folder sistem
string tmpFolder = Path.GetTempPath(); // Folder temp sistem
string desktop = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
// Buat direktori jika belum ada
Directory.CreateDirectory(folder);
Console.WriteLine($"Folder '{folder}' siap digunakan.");
Async File I/O — Tidak Memblokir Thread
Untuk aplikasi yang responsif (web, desktop), gunakan async I/O:
using System.IO;
// Async baca — tidak memblokir thread utama
async Task<string> BacaFileAsync(string path)
{
if (!File.Exists(path))
throw new FileNotFoundException($"File tidak ditemukan: {path}");
return await File.ReadAllTextAsync(path);
}
// Async tulis
async Task TulisLogAsync(string path, string pesan)
{
string entri = $"[{DateTime.Now:HH:mm:ss}] {pesan}\n";
await File.AppendAllTextAsync(path, entri);
}
// Penggunaan
async Task JalankanAsync()
{
// Tulis dan baca secara async
await TulisLogAsync("app.log", "Aplikasi dimulai");
await TulisLogAsync("app.log", "Proses data...");
await TulisLogAsync("app.log", "Selesai");
string isiLog = await BacaFileAsync("app.log");
Console.WriteLine(isiLog);
}
Praktik: Aplikasi Buku Kontak dengan File
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
class Kontak
{
public string Nama { get; set; }
public string Telepon { get; set; }
public string Email { get; set; }
}
class BukuKontak
{
private readonly string _path;
private List<Kontak> _kontak = new();
public BukuKontak(string path)
{
_path = path;
Muat();
}
// Muat data dari file
private void Muat()
{
if (!File.Exists(_path)) return;
foreach (string baris in File.ReadAllLines(_path))
{
if (string.IsNullOrWhiteSpace(baris)) continue;
string[] bagian = baris.Split('|');
if (bagian.Length < 3) continue;
_kontak.Add(new Kontak
{
Nama = bagian[0],
Telepon = bagian[1],
Email = bagian[2]
});
}
Console.WriteLine($"Memuat {_kontak.Count} kontak dari {_path}");
}
// Simpan semua kontak ke file
private void Simpan()
{
var baris = _kontak.Select(k => $"{k.Nama}|{k.Telepon}|{k.Email}");
File.WriteAllLines(_path, baris);
}
public void Tambah(string nama, string telepon, string email)
{
_kontak.Add(new Kontak { Nama = nama, Telepon = telepon, Email = email });
Simpan();
Console.WriteLine($"Kontak '{nama}' berhasil ditambahkan.");
}
public void Tampilkan()
{
if (_kontak.Count == 0)
{
Console.WriteLine("Buku kontak kosong.");
return;
}
Console.WriteLine($"\n{'Nama',-20} {'Telepon',-15} {'Email',-25}");
Console.WriteLine(new string('-', 62));
foreach (var k in _kontak.OrderBy(k => k.Nama))
Console.WriteLine($"{k.Nama,-20} {k.Telepon,-15} {k.Email,-25}");
}
public bool Hapus(string nama)
{
int sebelum = _kontak.Count;
_kontak = _kontak.Where(k => !k.Nama.Equals(nama, StringComparison.OrdinalIgnoreCase)).ToList();
if (_kontak.Count < sebelum) { Simpan(); return true; }
return false;
}
}
// Penggunaan
var buku = new BukuKontak("kontak.txt");
buku.Tambah("Ali Akbar", "08123456789", "ali@email.com");
buku.Tambah("Budi Santoso", "08987654321", "budi@email.com");
buku.Tambah("Siti Rahayu", "08111222333", "siti@email.com");
buku.Tampilkan();
// Output:
// Nama Telepon Email
// --------------------------------------------------------------
// Ali Akbar 08123456789 ali@email.com
// Budi Santoso 08987654321 budi@email.com
// Siti Rahayu 08111222333 siti@email.com
Pertanyaan yang Sering Diajukan
Kapan menggunakan File.ReadAllText vs StreamReader?
Gunakan File.ReadAllText / File.ReadAllLines untuk file kecil-sedang (< beberapa MB) karena lebih ringkas. Gunakan StreamReader dengan ReadLine() untuk file besar karena membaca satu baris sekaligus tanpa memuat seluruh file ke memori — penting untuk file log besar atau data CSV jutaan baris.
Mengapa Path.Combine lebih baik daripada concatenasi string biasa?
Path.Combine("folder", "file.txt") secara otomatis menggunakan separator yang benar untuk sistem operasi (backslash di Windows, forward slash di Linux/Mac). Concatenasi manual "folder" + "\\" + "file.txt" akan gagal di Linux. Selain itu, Path.Combine menangani edge case seperti trailing slash yang tidak konsisten.
Apakah perlu try/catch saat menggunakan File class?
Ya. Operasi file bisa gagal karena banyak alasan: file tidak ada (FileNotFoundException), izin tidak cukup (UnauthorizedAccessException), disk penuh (IOException). Selalu tangkap IOException (atau lebih spesifik) di sekitar operasi file, terutama untuk path yang berasal dari input pengguna atau konfigurasi eksternal.
Apa perbedaan using untuk StreamReader dan await using untuk async stream?
using (synchronous) memanggil Dispose() secara sinkron. await using (C# 8+) memanggil DisposeAsync() secara asinkron — lebih baik untuk resource yang operasi Dispose-nya bisa async (seperti menutup koneksi jaringan). Untuk file lokal biasa, perbedaannya minimal — keduanya bekerja dengan baik.
Kesimpulan
| Operasi | Cara C# | Kapan Digunakan |
|---|---|---|
| Baca semua | File.ReadAllText(path) | File kecil-sedang |
| Baca per baris | StreamReader.ReadLine() | File besar |
| Tulis baru | File.WriteAllText(path, isi) | Sederhana |
| Append | File.AppendAllText(path, isi) | Log file |
| Async baca | await File.ReadAllTextAsync(path) | Web/desktop apps |
| Path aman | Path.Combine(folder, file) | Selalu |
| Cek ada | File.Exists(path) | Sebelum baca |
Artikel sebelumnya: Exception Handling di C# — try/catch/finally dan using.
Selamat! Kamu sudah menguasai fondasi C# dari variabel hingga file I/O. Untuk langkah selanjutnya, pelajari C# dalam konteks web dengan ASP.NET Core — framework web server-side yang powerful.