skip to content

readText, bufferedReader & writeText

readText and writeText handle whole files in one call, while bufferedReader().use, forEachLine, and useLines stream them. The judgment being tested is when a file is small enough to slurp and when it is not.

part ofKotlinoverview, primer and where to startread it →
on this pageshow

questions

5

How do you read an entire file into a String and write a String to a file in Kotlin using the standard library? Name the relevant File extension functions.

level: juniorimportance: must knowfreq 75%

answer

  1. readText = whole file as String
  2. writeText truncates, appendText adds
  3. readLines = List<String>
  4. Default charset is UTF-8
  5. Eager: loads whole file into memory

basics

~10 s

Use File("path").readText() to get the whole file as one String, and File("path").writeText("content") to replace the file's contents. Both are Kotlin extension functions that open and close the file for you.

solid answer

~40 s

Kotlin's stdlib adds extension functions to java.io.File. `File.readText(charset = Charsets.UTF_8): String` reads the whole file into one String; `File.writeText(text, charset)` truncates the file and writes the String; `File.appendText(text)` adds to the end. `readLines(): List<String>` returns every line as a list. All of them open the underlying stream, do the work, and close it automatically, so you don't manage a Reader/Writer yourself. They default to UTF-8 but accept a Charset. They're convenient for small-to-medium files because the entire content is materialized in memory — for large files you'd stream with `bufferedReader().use { }`, `forEachLine`, or `useLines` instead. These functions throw IOException on failure (e.g. file missing, no permission).

code

kotlin · 9 lines
kotlin
import java.io.File

fun main() {
    val file = File("greeting.txt")
    file.writeText("Hello\n")
    file.appendText("World\n")
    println(file.readText())          // Hello\nWorld\n
    println(file.readLines())         // [Hello, World]
}

go deeper

for a junior

Knows readText/writeText exist and that writeText overwrites.

for a middle

Mentions UTF-8 default, appendText vs writeText, and that content is loaded into memory.

for a senior

Explains the eager-memory trade-off and points to streaming alternatives for large files; notes IOException handling.

for a principal

Frames these as convenience extensions over java.io and discusses charset correctness and memory/throughput limits at scale.

## What these are Kotlin doesn't ship its own file type — it reuses `java.io.File` and decorates it with **extension functions** in `kotlin.io`. An *extension function* lets you call `file.readText()` as if `readText` were a method on `File`, even though it isn't part of the Java class. ## Reading whole content - `File.readText(charset: Charset = Charsets.UTF_8): String` — reads the **entire** file into a single `String`. A *Charset* is the encoding (how bytes map to characters); the default is UTF-8. - `File.readLines(charset = Charsets.UTF_8): List<String>` — reads the file and returns each line as an element in a `List<String>`. Line breaks are stripped. - `File.readBytes(): ByteArray` — the raw bytes, for binary data. ## Writing whole content - `File.writeText(text: String, charset = Charsets.UTF_8)` — **truncates** (empties) the file, then writes the String. If the file doesn't exist it's created. - `File.appendText(text: String, charset = Charsets.UTF_8)` — keeps existing content and adds `text` to the end. - `File.writeBytes(array: ByteArray)` — write raw bytes. ```kotlin import java.io.File val f = File("notes.txt") f.writeText("line 1\n") // creates/overwrites f.appendText("line 2\n") // adds to end val whole: String = f.readText() // "line 1\nline 2\n" val lines: List<String> = f.readLines() // ["line 1", "line 2"] ``` ## Key properties - **They manage the stream for you.** Internally each one opens a `Reader`/`Writer`, performs the I/O, and closes it in a `finally` block — you never call `.close()`. - **They are eager and load everything into memory.** `readText`/`readLines` materialize the full file. That's fine for config files but dangerous for multi-gigabyte logs (risk of `OutOfMemoryError`). For those, stream with `bufferedReader().use`, `forEachLine`, or `useLines`. - **They can throw.** All do I/O, so they can throw `java.io.IOException` (subclasses like `FileNotFoundException`) — a checked-in-Java exception that Kotlin treats as unchecked but you should still handle. ## When to use what | Need | Use | |------|-----| | Small file, want one String | `readText()` | | Small file, want lines | `readLines()` | | Overwrite file | `writeText()` | | Append | `appendText()` | | Huge file | streaming (`useLines`, `forEachLine`) |

  • What charset do readText and writeText use by default?
    UTF-8 (Charsets.UTF_8). You can pass a different Charset as an argument.
  • Does writeText append or overwrite?
    It overwrites (truncates the file first). Use appendText to add to existing content.

readText is like photocopying a whole document at once; for a giant book you'd read page by page (streaming) instead.

saying these in an interview costs you the question

  • Thinking readText/writeText are methods on java.io.File rather than Kotlin extensions
  • Believing writeText appends instead of truncating
  • Claiming these handle arbitrarily large files safely
  • Saying you must manually close a stream after readText
  • Assuming the default charset is platform-default rather than UTF-8

context

open as a page

A teammate uses File.readLines() to process a 5 GB log file and the process runs out of memory. How would you fix it with the Kotlin stdlib, and why does that fix work?

level: middleimportance: must knowfreq 65%

basics

~20 s

readLines loads every line into memory at once. Replace it with useLines or forEachLine, which read the file line by line and only keep one line in memory at a time, so a huge file no longer blows up the heap.

open as a page

Show how to read a file line by line using bufferedReader().use, and explain what .use guarantees and why you'd choose it over readText.

level: middleimportance: should knowfreq 55%

basics

~20 s

Call file.bufferedReader().use { reader -> ... }. The use block runs your code and then always closes the reader, even if an error happens. You choose it over readText when the file is too big to load all at once.

open as a page

What charset do Kotlin's File text helpers use by default, and what concrete bugs arise if a file's actual encoding differs from what you read it with?

level: seniorimportance: should knowfreq 40%

basics

~20 s

Kotlin's readText, writeText, readLines, etc. default to UTF-8. If a file is actually in another encoding (like Latin-1 or UTF-16), reading it as UTF-8 corrupts non-ASCII characters or throws, because the bytes are decoded with the wrong rules.

open as a page

You're building a service that ingests user-uploaded files of unknown, possibly huge size and writes processed output that must be durable. Critique using File.readText/writeText here and describe what you'd reach for instead and why.

level: principalimportance: nice to knowfreq 25%

basics

~20 s

readText/writeText load or write the whole file at once and don't guarantee the data is safely saved to disk. For untrusted, possibly huge files you should stream and use atomic, flushed writes so you don't run out of memory or leave a half-written file.

open as a page