Isi berkas hanyalah separuh cerita; sistem operasi menyimpan cerita separuh sisanya sebagai metadata: berapa ukurannya, kapan terakhir diubah, berupa berkas biasa atau direktori, dan siapa boleh membacanya. Informasi semacam ini menentukan keputusan program sehari-hari — melewati berkas kosong, mendeteksi path yang ternyata direktori, mengurutkan hasil berdasarkan waktu ubah. java.nio.file menyediakan dua pintu menuju metadata: method serba-bisa Files.getAttribute() untuk satu atribut, dan Files.readAttributes() yang mengambil seluruh paket atribut dasar dalam satu panggilan sistem. Pada Chapter ini kita membaca atribut berkas nyata dan mengubah stempel waktu secara terprogram.

Membaca Atribut Dasar #

Files.getAttribute(path, "size") membaca satu atribut berdasarkan nama. Nama yang didukung pada tampilan basic meliputi size, isDirectory, isRegularFile, isSymbolicLink, lastModifiedTime, lastAccessTime, dan creationTime; nilai kembaliannya bertipe Object sehingga perlu diketahui tipenya. Setiap panggilan berarti satu perjalanan ke sistem berkas — bila kita butuh beberapa atribut sekaligus, Files.readAttributes(path, BasicFileAttributes.class) lebih efisien: JVM membuka satu panggilan sistem, mengisi objek BasicFileAttributes lengkap, lalu kita membaca field-nya dari memori sepuasnya.

Berkas pendamping laporan.txt (30 byte) menjadi objek pemeriksaan kita:

java BacaAtribut.java
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;

public class BacaAtribut {
    public static void main(String[] args) throws IOException {
        Path laporan = Path.of("laporan.txt");

        // Satu atribut per panggilan.
        System.out.println("size          : " + Files.getAttribute(laporan, "size"));
        System.out.println("isDirectory   : " + Files.getAttribute(laporan, "isDirectory"));
        System.out.println("isRegularFile : " + Files.getAttribute(laporan, "isRegularFile"));

        // Seluruh atribut dasar dalam satu pembacaan.
        BasicFileAttributes atribut =
                Files.readAttributes(laporan, BasicFileAttributes.class);
        System.out.println("ukuran        : " + atribut.size());
        System.out.println("berkas biasa : " + atribut.isRegularFile());
        System.out.println("direktori     : " + atribut.isDirectory());
        System.out.println("symbolic link : " + atribut.isSymbolicLink());
    }
}

Output yang Dihasilkan:

text
size          : 30
isDirectory   : false
isRegularFile : true
ukuran        : 30
berkas biasa : true
direktori     : false
symbolic link : false

Perhatikan tiga hal dari program dan keluarannya:

  1. Baris 10-13 (Files.getAttribute): tiga panggilan terpisah mengembalikan Object — Long untuk ukuran dan Boolean untuk pertanyaan jenis — yang langsung tersambung ke println. Ukuran 30 byte cocok dengan isi dua baris laporan.txt.
  2. Baris 16-17 (readAttributes): satu panggilan mengisi BasicFileAttributes, lalu atribut.size(), isRegularFile(), isDirectory(), dan isSymbolicLink() dibaca sebagai field objek tanpa menyentuh disk lagi.
  3. isSymbolicLink(): membedakan tautan dari targetnya — pemeriksaan yang tidak tersedia pada era java.io.File, dan penting sebelum menghapus atau menimpa path yang bisa jadi adalah tautan ke lokasi lain.

Mengubah Stempel Waktu #

Atribut tidak hanya dibaca — Files.setLastModifiedTime(path, FileTime) menulis ulang stempel waktu ubah milik berkas, dan Files.setAttribute bisa mengubah atribut lain lewat nama. Nilai waktunya bertipe FileTime, dibuat dari Instant melalui FileTime.from(instant); sebaliknya, FileTime.toInstant() mengubahnya kembali. Operasi seperti ini dipakai alat sinkronisasi dan arsip untuk memulihkan stempel asli setelah menyalin isi.

Program berikut menulis berkas baru, mengunci stempel waktunya ke sebuah Instant beku, lalu membacanya kembali sebagai bukti:

java AturWaktu.java
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.FileTime;
import java.time.Instant;

public class AturWaktu {
    public static void main(String[] args) throws IOException {
        Path berkas = Path.of("data-uji.txt");
        Files.writeString(berkas, "baris data uji\n");

        Instant momen = Instant.parse("2026-01-15T08:00:00Z");
        Files.setLastModifiedTime(berkas, FileTime.from(momen));

        FileTime terbaca = (FileTime) Files.getAttribute(berkas, "lastModifiedTime");
        System.out.println("lastModifiedTime : " + terbaca);
        System.out.println("sama dengan momen: " + terbaca.toInstant().equals(momen));
        System.out.println("detik epoch      : " + terbaca.toInstant().getEpochSecond());

        Files.delete(berkas);
    }
}

Output yang Dihasilkan:

text
lastModifiedTime : 2026-01-15T08:00:00Z
sama dengan momen: true
detik epoch      : 1768464000

Alurnya sederhana namun setiap langkahnya bermakna:

  1. Baris 11-12 (writeString): berkas baru tercipta dengan stempel waktu otomatis berisi waktu pembuatan — nilai yang berbeda tiap eksekusi, sehingga kita menimpanya agar hasil teruji ulang.
  2. Baris 14-15 (setLastModifiedTime): stempel diubah menjadi 15 Januari 2026 pukul 08:00 UTC — Instant beku yang sama dengan nilai yang dipakai param FileTime.from.
  3. Baris 17-20 (getAttribute kembali): pembacaan mengembalikan FileTime (perlu cast dari Object); representasi cetaknya 2026-01-15T08:00:00Z, kesetaraan dengan momen asal terbukti true, dan getEpochSecond() menyingkap angka mentahnya 1768464000 — detik sejak epoch Unix yang bisa diverifikasi dengan Instant.ofEpochSecond.

Satu keluarga atribut masih menyimpan kejutan: atribut view POSIX menyimpan per izin pengguna, grup, dan lainnya dalam bentuk yang bisa dibaca satu per satu — peta hak akses klasik Linux. Chapter berikutnya berfokus pada izin akses berkas: memeriksa keterbacaan, membaca permission POSIX, dan memahami keterbatasannya di platform tanpa POSIX seperti Windows.

Referensi #

Berkas Sumber

Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.

AturWaktu.java

Unduh berkas
java
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.FileTime;
import java.time.Instant;

public class AturWaktu {
    public static void main(String[] args) throws IOException {
        Path berkas = Path.of("data-uji.txt");
        Files.writeString(berkas, "baris data uji\n");

        Instant momen = Instant.parse("2026-01-15T08:00:00Z");
        Files.setLastModifiedTime(berkas, FileTime.from(momen));

        FileTime terbaca = (FileTime) Files.getAttribute(berkas, "lastModifiedTime");
        System.out.println("lastModifiedTime : " + terbaca);
        System.out.println("sama dengan momen: " + terbaca.toInstant().equals(momen));
        System.out.println("detik epoch      : " + terbaca.toInstant().getEpochSecond());

        Files.delete(berkas);
    }
}

BacaAtribut.java

Unduh berkas
java
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;

public class BacaAtribut {
    public static void main(String[] args) throws IOException {
        Path laporan = Path.of("laporan.txt");

        // Satu atribut per panggilan.
        System.out.println("size          : " + Files.getAttribute(laporan, "size"));
        System.out.println("isDirectory   : " + Files.getAttribute(laporan, "isDirectory"));
        System.out.println("isRegularFile : " + Files.getAttribute(laporan, "isRegularFile"));

        // Seluruh atribut dasar dalam satu pembacaan.
        BasicFileAttributes atribut =
                Files.readAttributes(laporan, BasicFileAttributes.class);
        System.out.println("ukuran        : " + atribut.size());
        System.out.println("berkas biasa : " + atribut.isRegularFile());
        System.out.println("direktori     : " + atribut.isDirectory());
        System.out.println("symbolic link : " + atribut.isSymbolicLink());
    }
}