Hampir semua aplikasi yang bermanfaat pada akhirnya menyentuh penyimpanan: membaca konfigurasi, menyimpan hasil olahan, atau menulis log. Sejak versi paling awal, Java menyediakan class java.io.File sebagai alat baku untuk mewakili nama berkas dan direktori di sistem operasi. Sebuah objek File bukan pegangan ke isi berkas, melainkan wakil dari sebuah pathname yang bisa kita periksa, buat, atau hapus. Pada Chapter ini kita berkenalan dengan File, menjalankan operasi sistem berkas dasar, lalu memahami mengapa API modern java.nio.file.Path menggantikannya di kode baru.
File sebagai Wakil Pathname #
Class File membungkus sebuah string path dan memberi method untuk bertanya kepada sistem operasi tentang path tersebut. Ketika kita memanggil exists() atau length(), JVM meneruskan pertanyaan itu ke panggilan sistem (system call) milik sistem operasi; sebelum method dipanggil, objek File hanyalah data di memori dan tidak menyentuh disk sama sekali. Konsekuensinya, dua objek File berbeda boleh menunjuk path yang sama, dan kondisi di disk dapat berubah kapan pun di luar kendali program kita.
Berkas pendamping daftar.txt berisi tiga baris nama dan akan menjadi kelinci percobaan kita. Program berikut memeriksa berkas itu, lalu mencoba membuat serta menghapus sebuah direktori:
import java.io.File;
public class MengujiFile {
public static void main(String[] args) {
File daftar = new File("daftar.txt");
File arsip = new File("arsip");
File tingkat = new File("tingkat/dua");
System.out.println("daftar.txt ada : " + daftar.exists());
System.out.println("daftar.txt isFile : " + daftar.isFile());
System.out.println("daftar.txt isDir : " + daftar.isDirectory());
System.out.println("daftar.txt length : " + daftar.length() + " byte");
System.out.println("daftar.txt canRead : " + daftar.canRead());
System.out.println("arsip ada (awal) : " + arsip.exists());
System.out.println("mkdir arsip : " + arsip.mkdir());
System.out.println("arsip isDirectory : " + arsip.isDirectory());
System.out.println("mkdir tingkat/dua : " + tingkat.mkdir());
System.out.println("tingkat/dua ada : " + tingkat.exists());
System.out.println("delete arsip : " + arsip.delete());
System.out.println("arsip ada (akhir) : " + arsip.exists());
System.out.println("delete tidakada.txt : " + new File("tidakada.txt").delete());
}
}Output yang Dihasilkan:
daftar.txt ada : true
daftar.txt isFile : true
daftar.txt isDir : false
daftar.txt length : 15 byte
daftar.txt canRead : true
arsip ada (awal) : false
mkdir arsip : true
arsip isDirectory : true
mkdir tingkat/dua : false
tingkat/dua ada : false
delete arsip : true
arsip ada (akhir) : false
delete tidakada.txt : falseMari kita telaah baris-baris kode di atas:
- Baris 5-7 (
new File(...)): membuat tiga objekFiledari path relatif terhadap direktori kerja program.daftar.txtmerujuk berkas nyata di bundle, sedangkanarsipdantingkat/duabelum ada di disk. - Baris 9-13 (
exists,isFile,isDirectory,length): menginterogasi sistem berkas.daftar.txtterbukti ada, berupa berkas biasa (bukan direktori), berukuran 15 byte — tepat 15 karakter dari teksBudi,Siti,Dewibeserta tanda baris baru. - Baris 15-19 (
mkdir):mkdir()hanya membuat satu level direktori. Karena direktori induktingkatbelum ada, pemanggilan untuktingkat/duamengembalikanfalsetanpa membuat apa pun; gunakanmkdirs()bila seluruh rantai induk perlu dibuat sekaligus. - Baris 21-24 (
delete): penghapusan direktori hanya berhasil bila direktori kosong, dan penghapusan berkas yang tidak ada mengembalikanfalse— bukan exception.
Perhatikan pola penting di sini: hampir semua operasi File mengembalikan boolean, bukan void. Kita wajib memeriksa nilai kembalian tersebut; mengabaikannya berarti program berjalan seolah berhasil padahal perubahan di disk gagal terjadi.
Mengelola Direktori dan Isinya #
Untuk bekerja dengan isi direktori, File menyediakan list() yang mengembalikan array nama, createNewFile() yang membuat berkas kosong, dan renameTo() yang memindahkan atau mengganti nama. Program berikut menyusun direktori kerja kecil, mengurutkan isinya, lalu membersihkannya kembali:
import java.io.File;
import java.util.Arrays;
public class KelolaIsiDirektori {
public static void main(String[] args) throws Exception {
File arsip = new File("arsip");
System.out.println("mkdir arsip : " + arsip.mkdir());
File pertama = new File(arsip, "a.txt");
File kedua = new File(arsip, "b.log");
System.out.println("createNewFile a : " + pertama.createNewFile());
System.out.println("createNewFile b : " + kedua.createNewFile());
String[] isi = arsip.list();
Arrays.sort(isi);
System.out.println("isi arsip : " + Arrays.toString(isi));
File baru = new File(arsip, "c.txt");
System.out.println("renameTo c.txt : " + pertama.renameTo(baru));
System.out.println("a.txt masih ada : " + pertama.exists());
System.out.println("c.txt sudah ada : " + baru.exists());
// Pembersihan: direktori hanya bisa dihapus bila kosong.
for (String nama : arsip.list()) {
new File(arsip, nama).delete();
}
System.out.println("delete arsip : " + arsip.delete());
}
}Output yang Dihasilkan:
mkdir arsip : true
createNewFile a : true
createNewFile b : true
isi arsip : [a.txt, b.log]
renameTo c.txt : true
a.txt masih ada : false
c.txt sudah ada : true
delete arsip : trueTiga detail layak digarisbawahi dari keluaran di atas. Pertama, Arrays.sort() dipanggil sebelum mencetak list() karena urutan yang dikembalikan sistem operasi tidak dijamin — pengurutan eksplisit membuat program portabel dan keluarannya dapat diuji ulang. Kedua, renameTo() memindahkan pegangan: setelah pemanggilan berhasil, objek lama a.txt melaporkan exists() bernilai false dan objek c.txt bernilai true. Ketiga, pembersihan dilakukan berurutan dari berkas ke direktori karena delete() menolak direktori yang masih berisi.
Kelemahan Platform dan Status Legacy #
Class File memang berumur panjang, tetapi usianya menampakkan beberapa kelemahan desain. Nilai kembalian boolean tidak pernah menjelaskan alasan kegagalan — berkas terkunci, izin ditolak, atau path memang tidak ada semuanya tampak sama, sehingga mendiagnosis masalah produksi menjadi sulit. Perilakunya juga bergantung platform: di Windows, File.txt dan file.txt dianggap path yang sama karena sistem berkasnya tidak membedakan huruf besar-kecil, sedangkan di Linux keduanya adalah dua berkas berbeda. Dukungan terhadap symbolic link dan atribut berkas modern juga terbatas.
Karena alasan tersebut, kode baru sebaiknya memakai java.nio.file.Path dan java.nio.file.Files yang akan kita bahas sepanjang sisa Section ini. Class File tetap sering dijumpai pada pustaka lama, framework yang berumur panjang, dan API lawas seperti beberapa method di java.util.jar, sehingga kemampuan membacanya tetap berguna. Jembatan dua arah tersedia: file.toPath() mengubah objek File menjadi Path modern, dan path.toFile() bekerja sebaliknya.
Dengan bekal pemahaman akan API klasik ini, kita siap berpindah ke fondasi modern I/O Java. Chapter berikutnya memperkenalkan java.nio.file.Path, tipe immutable yang merepresentasikan path secara lebih presisi beserta operasi manipulasi yang kaya.
Referensi #
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
KelolaIsiDirektori.java
Unduh berkasimport java.io.File;
import java.util.Arrays;
public class KelolaIsiDirektori {
public static void main(String[] args) throws Exception {
File arsip = new File("arsip");
System.out.println("mkdir arsip : " + arsip.mkdir());
File pertama = new File(arsip, "a.txt");
File kedua = new File(arsip, "b.log");
System.out.println("createNewFile a : " + pertama.createNewFile());
System.out.println("createNewFile b : " + kedua.createNewFile());
String[] isi = arsip.list();
Arrays.sort(isi);
System.out.println("isi arsip : " + Arrays.toString(isi));
File baru = new File(arsip, "c.txt");
System.out.println("renameTo c.txt : " + pertama.renameTo(baru));
System.out.println("a.txt masih ada : " + pertama.exists());
System.out.println("c.txt sudah ada : " + baru.exists());
// Pembersihan: direktori hanya bisa dihapus bila kosong.
for (String nama : arsip.list()) {
new File(arsip, nama).delete();
}
System.out.println("delete arsip : " + arsip.delete());
}
}
MengujiFile.java
Unduh berkasimport java.io.File;
public class MengujiFile {
public static void main(String[] args) {
File daftar = new File("daftar.txt");
File arsip = new File("arsip");
File tingkat = new File("tingkat/dua");
System.out.println("daftar.txt ada : " + daftar.exists());
System.out.println("daftar.txt isFile : " + daftar.isFile());
System.out.println("daftar.txt isDir : " + daftar.isDirectory());
System.out.println("daftar.txt length : " + daftar.length() + " byte");
System.out.println("daftar.txt canRead : " + daftar.canRead());
System.out.println("arsip ada (awal) : " + arsip.exists());
System.out.println("mkdir arsip : " + arsip.mkdir());
System.out.println("arsip isDirectory : " + arsip.isDirectory());
System.out.println("mkdir tingkat/dua : " + tingkat.mkdir());
System.out.println("tingkat/dua ada : " + tingkat.exists());
System.out.println("delete arsip : " + arsip.delete());
System.out.println("arsip ada (akhir) : " + arsip.exists());
System.out.println("delete tidakada.txt : " + new File("tidakada.txt").delete());
}
}