Section File I/O dimulai dengan dua abstraksi dasar yang dipakai Kotlin untuk memanipulasi file: java.io.File dan java.nio.file.Path. Kotlin tidak memiliki API file sendiri — ia mengandalkan Java standard library. java.io.File hadir sejak versi awal Java dan menjadi API klasik; java.nio.file.Path diperkenalkan di Java 7 sebagai bagian dari NIO.2 dengan fitur yang lebih kaya dan aman. Bab ini memperkenalkan kedua representasi, perbedaannya, dan operasi properti dasar yang paling sering dipakai.

java.io.File: API Klasik #

java.io.File adalah representasi abstrak dari path file atau direktori. Kelas ini tersedia di Kotlin melalui import java.io.File. Properti paling sering dipakai: path, parent, name, extension, dan nameWithoutExtension.

kotlin
import java.io.File
import java.nio.file.Path
import java.nio.file.Paths
import java.nio.file.Files
import java.nio.file.attribute.FileTime
import java.time.Instant

const val DEMO_DIR = "/tmp/kotlin-tutorial-file-fundamentals"

fun main() {
    // Bersihkan dir demo jika ada dari run sebelumnya
    File(DEMO_DIR).deleteRecursively()
    File(DEMO_DIR).mkdirs()

    println("=== 1. java.io.File: representasi file teks ===")
    val fileA = File("data/contoh.txt")
    println("path = ${fileA.path}")
    println("parent = ${fileA.parent}")
    println("name = ${fileA.name}")
    println("extension = ${fileA.extension}")
    println("nameWithoutExtension = ${fileA.nameWithoutExtension}")

    println()
    println("=== 2. java.nio.file.Path: representasi modern ===")
    val pathA: Path = Paths.get("data/contoh.txt")
    println("toString = $pathA")
    println("fileName = ${pathA.fileName}")
    println("parent = ${pathA.parent}")
    println("root = ${pathA.root}")

    println()
    println("=== 3. Membuat file demo di direktori tetap ===")
    val fileDemo = File("$DEMO_DIR/catatan.txt")
    fileDemo.writeText("baris pertama")
    println("fileDemo.path (relatif terhadap dir demo) = ${File(fileDemo.parentFile.name, fileDemo.name).path}")
    println("fileDemo.absolutePath = <tmp>/${fileDemo.parentFile.name}/${fileDemo.name}")

    println()
    println("=== 4. Properti umum: exists, isDirectory, isFile, length ===")
    println("exists = ${fileDemo.exists()}")
    println("isDirectory = ${fileDemo.isDirectory}")
    println("isFile = ${fileDemo.isFile}")
    println("length (bytes) = ${fileDemo.length()}")

    println()
    println("=== 5. lastModified: waktu modifikasi terakhir (di-set eksplisit) ===")
    val waktuTetap = Instant.parse("2026-01-15T08:30:00Z").toEpochMilli()
    fileDemo.setLastModified(waktuTetap)
    val lastMod = FileTime.from(Instant.ofEpochMilli(fileDemo.lastModified()))
    println("lastModified (FileTime) = ${lastMod.toString().substringBefore('.')}")

    println()
    println("=== 6. Direktori vs File ===")
    val dirDemo = File(DEMO_DIR)
    println("dirDemo.isDirectory = ${dirDemo.isDirectory}")
    println("fileDemo.isDirectory = ${fileDemo.isDirectory}")
    println("dirDemo.name = ${dirDemo.name}")

    println()
    println("=== 7. File vs Path: kapan memakai yang mana ===")
    val dariFile: Path = fileDemo.toPath()  // konversi File -> Path
    val dariPath: File = pathA.toFile()     // konversi Path -> File
    println("File.toPath().fileName = ${dariFile.fileName}")
    println("Path.toFile().name = ${dariPath.name}")
    println("Path.toFile().exists (file 'data/contoh.txt' belum dibuat) = ${dariPath.exists()}")

    println()
    println("=== 8. Bersih-bersih ===")
    fileDemo.delete()
    println("fileDemo.exists setelah delete = ${fileDemo.exists()}")
    dirDemo.delete()
    println("dirDemo.exists setelah delete = ${dirDemo.exists()}")
}

Output yang Dihasilkan:

text
=== 1. java.io.File: representasi file teks ===
path = data/contoh.txt
parent = data
name = contoh.txt
extension = txt
nameWithoutExtension = contoh

=== 2. java.nio.file.Path: representasi modern ===
toString = data/contoh.txt
fileName = contoh.txt
parent = data
root = null

=== 3. Membuat file demo di direktori tetap ===
fileDemo.path (relatif terhadap dir demo) = kotlin-tutorial-file-fundamentals/catatan.txt
fileDemo.absolutePath = <tmp>/kotlin-tutorial-file-fundamentals/catatan.txt

=== 4. Properti umum: exists, isDirectory, isFile, length ===
exists = true
isDirectory = false
isFile = true
length (bytes) = 13

=== 5. lastModified: waktu modifikasi terakhir (di-set eksplisit) ===
lastModified (FileTime) = 2026-01-15T08:30:00Z

=== 6. Direktori vs File ===
dirDemo.isDirectory = true
fileDemo.isDirectory = false
dirDemo.name = kotlin-tutorial-file-fundamentals

=== 7. File vs Path: kapan memakai yang mana ===
File.toPath().fileName = catatan.txt
Path.toFile().name = contoh.txt
Path.toFile().exists (file 'data/contoh.txt' belum dibuat) = false

=== 8. Bersih-bersih ===
fileDemo.exists setelah delete = false
dirDemo.exists setelah delete = false

Mari kita bedah bagian-bagian penting:

  1. Bagian 1 (java.io.File): membuat File("data/contoh.txt") tidak langsung membuat file di disk — File hanyalah representasi path. Properti extension (.txt) dan nameWithoutExtension (contoh) adalah extension function Kotlin yang membuat java.io.File lebih nyaman dipakai daripada versi Java aslinya.
  2. Bagian 2 (java.nio.file.Path): Paths.get("data/contoh.txt") membuat Path — juga tidak menyentuh disk. Properti root bernilai null karena path relatif. Untuk path absolut seperti /var/log/app.log, root akan bernilai /.
  3. Bagian 3 (membuat file demo): writeText("baris pertama") adalah extension function Kotlin yang menulis teks ke file dan otomatis menutup resource. File benar-benar ada di disk setelah pemanggilan ini.
  4. Bagian 4 (exists, isDirectory, isFile, length): empat properti paling sering dipakai. exists() memeriksa keberadaan; isDirectory dan isFile saling melengkapi; length() mengembalikan ukuran dalam byte. File “baris pertama” = 13 byte (12 karakter ASCII + 0 newline karena writeText tidak menambah newline).
  5. Bagian 5 (lastModified): waktu modifikasi terakhir sebagai epoch milliseconds. Kita pakai Instant.parse("2026-01-15T08:30:00Z") dan setLastModified agar output deterministik. Untuk file yang baru ditulis, lastModified adalah waktu saat ini — tidak deterministik untuk pengujian.
  6. Bagian 6 (Direktori vs File): isDirectory membedakan folder dari file biasa. Direktori yang tidak ada punya isDirectory = false. Untuk memastikan ada, gunakan exists() && isDirectory.
  7. Bagian 7 (konversi): File.toPath() dan Path.toFile() menghubungkan kedua API. Penting: Path.toFile() mengembalikan File yang merepresentasikan path tersebut — apakah file itu ada di disk, tergantung pada apakah sudah dibuat. Output membuktikan data/contoh.txt belum dibuat, sehingga exists = false.

File vs Path: Mana yang Dipakai #

Pertanyaan umum: kapan memakai File, kapan Path? Aturan praktis:

Aspekjava.io.Filejava.nio.file.Path
Tahun diperkenalkanJava 1.0 (1996)Java 7 (2011)
KemampuanOperasi dasar (read, write, list, delete)Operasi dasar + fitur lanjutan
Symbolic linkTidak mendukung penuhMendukung penuh via Files
File attributeslastModified, length, canReadMendukung BasicFileAttributes, PosixFileAttributes
Atomic moveTidak dijaminFiles.move dengan ATOMIC_MOVE
Error handlingMengembalikan falseMelempar exception dengan pesan
RekomendasiKompatibilitas mundurKode baru (rekomendasi resmi)

Operasi Properti Lainnya #

Beberapa operasi properti yang juga sering dipakai:

OperasiMengembalikan
File.canRead()Boolean — apakah aplikasi bisa membaca file
File.canWrite()Boolean — apakah aplikasi bisa menulis
File.isHiddenBoolean — apakah file dianggap hidden
File.absolutePathString path absolut
File.canonicalPathString path setelah resolve .. dan symbolic link
Files.isSymbolicLink(path)Boolean — apakah path adalah symbolic link

Referensi Lanjutan #

Selanjutnya #

Bab berikutnya, java.io Interoperability, akan membahas extension function Kotlin di java.io.File untuk operasi baca-tulis teks: File.readText(), File.writeText(), File.readLines(), dan File.useLines { }. Fungsi-fungsi ini menyembunyikan boilerplate stream Java dan membuat kode Kotlin terasa ringkas.