Setelah Path merepresentasikan nama, class java.nio.file.Files mengambil alih pekerjaan beratnya. Semua method di Files bersifat static, menerima Path sebagai argumen, dan membungkus panggilan sistem operasi menjadi satu baris kode: memeriksa keberadaan, membaca seluruh isi, menyalin, memindahkan, hingga memproses berkas baris demi baris sebagai stream. Sejak Java 11 hadir pula readString dan writeString yang menyederhanakan kasus paling sering — berkas teks kecil. Pada Chapter ini kita menyusuri method yang paling sering terpakai, lengkap dengan pola penanganan exception yang menyertainya.
Operasi Berkas Sehari-hari #
Berbeda dari java.io.File yang mengembalikan boolean untuk segalanya, Files melempar IOException beserta subclass-nya ketika operasi gagal. Kegagalan pun menjadi informatif: NoSuchFileException membawa nama berkas, FileAlreadyExistsException memberi tahu target yang bentrok. Method menulis juga menerima varargs OpenOption seperti CREATE, APPEND, atau REPLACE_EXISTING — tanpa opsi, writeString mengganti isi berkas lama atau membuat berkas baru bila belum ada.
Program berikut merangkai delapan operasi umum terhadap berkas pendamping artikel.txt:
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
public class TugasBerkas {
public static void main(String[] args) throws IOException {
Path artikel = Path.of("artikel.txt");
System.out.println("exists : " + Files.exists(artikel));
System.out.println("size : " + Files.size(artikel) + " byte");
String isi = Files.readString(artikel, StandardCharsets.UTF_8);
System.out.println("readString : " + isi.lines().count() + " baris");
System.out.println("kata pertama : " + isi.split(" ")[0]);
Path salinan = Path.of("salinan.txt");
Files.copy(artikel, salinan, StandardCopyOption.REPLACE_EXISTING);
System.out.println("copy : ukuran sama = "
+ (Files.size(salinan) == Files.size(artikel)));
Path arsip = Path.of("arsip.txt");
Files.move(salinan, arsip, StandardCopyOption.REPLACE_EXISTING);
System.out.println("move : salinan ada = " + Files.exists(salinan)
+ ", arsip ada = " + Files.exists(arsip));
long jumlahBaris;
try (var stream = Files.lines(arsip, StandardCharsets.UTF_8)) {
jumlahBaris = stream.count();
}
System.out.println("lines : " + jumlahBaris + " baris");
Path target = Path.of("catatan", "2026", "ringkasan.txt");
Files.createDirectories(target.getParent());
Files.writeString(target, "Diproses oleh Files.\n", StandardCharsets.UTF_8);
try (BufferedReader pembaca = Files.newBufferedReader(target, StandardCharsets.UTF_8)) {
System.out.println("newBufferedReader: " + pembaca.readLine());
}
System.out.println("delete : " + Files.deleteIfExists(arsip));
System.out.println("arsip ada : " + Files.exists(arsip));
}
}Output yang Dihasilkan:
exists : true
size : 91 byte
readString : 3 baris
kata pertama : Belajar
copy : ukuran sama = true
move : salinan ada = false, arsip ada = true
lines : 3 baris
newBufferedReader: Diproses oleh Files.
delete : true
arsip ada : falseMari kita bedah operasi demi operasi:
- Baris 13-14 (
exists,size): dua pertanyaan paling dasar.size()mengembalikan ukuran dalam byte dan melempar exception bila berkasnya tidak ada — berbeda dariFile.length()yang mengembalikan0tanpa penjelasan. - Baris 16-18 (
readString): membaca seluruh berkas teks menjadi satuString. Charset UTF-8 selalu dinyatakan eksplisit agar hasilnya sama di semua mesin, bukan bergantung pada locale sistem operasi. - Baris 21-23 (
copy): menyalin dengan opsiREPLACE_EXISTINGagar berkas salinan lama tertimpa; tanpa opsi itu, menimpa berkas yang sudah ada melemparFileAlreadyExistsException. - Baris 26-28 (
move): memindahkan atau mengganti nama. Setelahmoveberhasil, path sumbersalinan.txttidak lagi ada — keluaran memperlihatkan peralihan tersebut. - Baris 31-34 (
Files.linesdalam try-with-resources): menghasilkanStream<String>yang dibuka malas (lazily); stream ini memegang pegangan berkas sehingga wajib ditutup, dan try-with-resources menutupnya otomatis. - Baris 37-42 (
createDirectories+writeString+newBufferedReader): membuat seluruh rantai foldercatatan/2026sekaligus, menulis satu baris, lalu membacanya kembali denganBufferedReader— pola baca-tulis-tuntaskan.
Menangani Berkas yang Tidak Ada #
Ketika berkas hilang, Files tidak diam melainkan melempar NoSuchFileException, subclass dari IOException yang menyimpan nama berkas penyebab. Karena exception ini spesifik, blok catch bisa membedakan “berkas memang tidak ada” dari “ada tetapi tidak bisa dibaca”. Kasus kedua yang sering menjatuhkan pemula: menulis ke path bertingkat ketika folder induknya belum dibuat.
Program berikut mengalami kedua kejadian itu lalu pulih darinya:
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
public class TanganiHilang {
public static void main(String[] args) {
Path konfigurasi = Path.of("konfigurasi.yaml");
try {
String isi = Files.readString(konfigurasi);
System.out.println("terbaca: " + isi);
} catch (NoSuchFileException e) {
System.out.println("berkas tidak ada : " + e.getFile());
} catch (IOException e) {
System.out.println("I/O gagal : " + e.getClass().getSimpleName());
}
Path target = Path.of("hasil", "laporan.txt");
try {
Files.writeString(target, "isi laporan", StandardCharsets.UTF_8);
System.out.println("tulis langsung : sukses");
} catch (NoSuchFileException e) {
System.out.println("tulis langsung : gagal, induk belum ada");
} catch (IOException e) {
System.out.println("tulis langsung : gagal, "
+ e.getClass().getSimpleName());
}
try {
Files.createDirectories(target.getParent());
Files.writeString(target, "isi laporan", StandardCharsets.UTF_8);
String hasil = Files.readString(target, StandardCharsets.UTF_8);
System.out.println("setelah buat induk: " + hasil);
} catch (IOException e) {
System.out.println("gagal total: " + e.getClass().getSimpleName());
}
}
}Output yang Dihasilkan:
berkas tidak ada : konfigurasi.yaml
tulis langsung : gagal, induk belum ada
setelah buat induk: isi laporanUrutan blok catch pada segmen pertama memegang peran penting: NoSuchFileException ditangkap lebih dulu karena class tersebut lebih spesifik, disusul IOException umum sebagai jaring pengaman — compiler Java menolak urutan terbalik karena subclass tidak akan pernah terjangkau. Segmen kedua membuktikan bahwa writeString ke hasil/laporan.txt gagal selama folder hasil belum dibuat, padahal exception-nya tetap NoSuchFileException. Setelah createDirectories(target.getParent()) menyiapkan induknya, penulisan yang sama berhasil dan isi terbaca kembali — pola gagal-kenali-perbaiki yang tuntas.
Sebagai peta ringkas, berikut method Files yang paling sering terpakai:
| Kebutuhan | Method | Catatan |
|---|---|---|
| Periksa | exists, size, isRegularFile | tanpa exception |
| Baca teks | readString, lines, newBufferedReader | sebutkan charset |
| Tulis teks | writeString, newBufferedWriter | opsi APPEND, CREATE |
| Salin / pindah | copy, move | REPLACE_EXISTING menimpa |
| Hapus | delete, deleteIfExists | folder harus kosong |
| Struktur | createDirectories | buat seluruh rantai induk |
Di balik method singkat ini, Files tetap membuka stream byte dan karakter seperti biasa. Chapter berikutnya membuka selubung itu: kita akan bekerja langsung dengan InputStream dan OutputStream untuk memproses data biner mentah byte demi byte.
Referensi #
- Oracle: Class Files (Java SE 25 API)
- Oracle: Class NoSuchFileException (Java SE 25 API)
- dev.java: Java I/O
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
TanganiHilang.java
Unduh berkasimport java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
public class TanganiHilang {
public static void main(String[] args) {
Path konfigurasi = Path.of("konfigurasi.yaml");
try {
String isi = Files.readString(konfigurasi);
System.out.println("terbaca: " + isi);
} catch (NoSuchFileException e) {
System.out.println("berkas tidak ada : " + e.getFile());
} catch (IOException e) {
System.out.println("I/O gagal : " + e.getClass().getSimpleName());
}
Path target = Path.of("hasil", "laporan.txt");
try {
Files.writeString(target, "isi laporan", StandardCharsets.UTF_8);
System.out.println("tulis langsung : sukses");
} catch (NoSuchFileException e) {
System.out.println("tulis langsung : gagal, induk belum ada");
} catch (IOException e) {
System.out.println("tulis langsung : gagal, "
+ e.getClass().getSimpleName());
}
try {
Files.createDirectories(target.getParent());
Files.writeString(target, "isi laporan", StandardCharsets.UTF_8);
String hasil = Files.readString(target, StandardCharsets.UTF_8);
System.out.println("setelah buat induk: " + hasil);
} catch (IOException e) {
System.out.println("gagal total: " + e.getClass().getSimpleName());
}
}
}
TugasBerkas.java
Unduh berkasimport java.io.BufferedReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
public class TugasBerkas {
public static void main(String[] args) throws IOException {
Path artikel = Path.of("artikel.txt");
System.out.println("exists : " + Files.exists(artikel));
System.out.println("size : " + Files.size(artikel) + " byte");
String isi = Files.readString(artikel, StandardCharsets.UTF_8);
System.out.println("readString : " + isi.lines().count() + " baris");
System.out.println("kata pertama : " + isi.split(" ")[0]);
Path salinan = Path.of("salinan.txt");
Files.copy(artikel, salinan, StandardCopyOption.REPLACE_EXISTING);
System.out.println("copy : ukuran sama = "
+ (Files.size(salinan) == Files.size(artikel)));
Path arsip = Path.of("arsip.txt");
Files.move(salinan, arsip, StandardCopyOption.REPLACE_EXISTING);
System.out.println("move : salinan ada = " + Files.exists(salinan)
+ ", arsip ada = " + Files.exists(arsip));
long jumlahBaris;
try (var stream = Files.lines(arsip, StandardCharsets.UTF_8)) {
jumlahBaris = stream.count();
}
System.out.println("lines : " + jumlahBaris + " baris");
Path target = Path.of("catatan", "2026", "ringkasan.txt");
Files.createDirectories(target.getParent());
Files.writeString(target, "Diproses oleh Files.\n", StandardCharsets.UTF_8);
try (BufferedReader pembaca = Files.newBufferedReader(target, StandardCharsets.UTF_8)) {
System.out.println("newBufferedReader: " + pembaca.readLine());
}
System.out.println("delete : " + Files.deleteIfExists(arsip));
System.out.println("arsip ada : " + Files.exists(arsip));
}
}