Skip to content
AgileLogics
5 min read

Working with Files

Prerequisites: Exceptions and error handling

On the JVM, Kotlin reads and writes files with Java's file APIs plus a set of convenient Kotlin extension functions.

Reading and writing whole files

import java.io.File

fun main() {
    val file = File.createTempFile("notes", ".txt")

    file.writeText("First line\nSecond line\n")
    file.appendText("Third line\n")

    println(file.readText().trim())
    println(file.readLines().size)
    println(file.exists())

    file.delete()
    println(file.exists())
}
First line
Second line
Third line
3
true
false

writeText replaces the contents; appendText adds to the end. Both use UTF-8 by default.

Large files: read line by line

readText and readLines load the whole file into memory. For big files, process one line at a time:

import java.io.File

fun main() {
    val log = File.createTempFile("app", ".log")
    log.writeText("INFO start\nERROR disk full\nINFO retry\nERROR timeout\n")

    val errors = log.useLines { lines ->
        lines.filter { it.startsWith("ERROR") }.map { it.removePrefix("ERROR ") }.toList()
    }
    println(errors)
    log.delete()
}
[disk full, timeout]

useLines opens the file, gives you the lines as a lazy sequence, and closes the file automatically when the block ends.

Closing resources: use

Anything that must be closed — files, streams, database connections — should be wrapped in use, which closes it even if an exception is thrown:

File("report.csv").bufferedWriter().use { out ->
    out.write("name,total\n")
    out.write("Ada,120\n")
}

Paths and folders

import java.io.File

fun main() {
    val dir = File(System.getProperty("java.io.tmpdir"), "kt-demo")
    dir.mkdirs()
    File(dir, "a.txt").writeText("a")
    File(dir, "b.md").writeText("b")

    println(dir.listFiles()!!.map { it.name }.sorted())
    println(File("photo.jpeg").extension)
    println(File("photo.jpeg").nameWithoutExtension)
    dir.deleteRecursively()
}
[a.txt, b.md]
jpeg
photo

The newer java.nio.file.Path API, with Kotlin extensions in kotlin.io.path, is also widely used and handles some edge cases better.

Common mistakes

  • Reading a missing file: FileNotFoundException. Check exists() or catch the exception.
  • Relative paths are relative to the working directory — where the program was started from — not to the source file.