Working with Files and the File System in Kotlin: From Beginner to Pro

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Why working with files in Kotlin doesn't have to be painful

\n\n

Imagine: you are writing an application that needs to save user settings, log errors, or process CSV files with thousands of lines. In Java, this involves dozens of classes like BufferedReader, FileWriter, and endless try-catch blocks. But what about Kotlin? The language created by JetBrains doesn't just "simplify" Java — it rethinks data handling. Here, files are opened with a single line of code, and errors are handled elegantly.

\n\n

In this article, we will cover working with files and the file system in Kotlin from basic operations to advanced techniques. You will learn how to read and write files, manage directories, work with JSON and CSV, and avoid common mistakes. Ready? Let's go!

\n\n

Basics: How Kotlin simplifies Java IO

\n\n

The main feature of Kotlin is extension functions. Instead of writing dozens of lines to read a file, you use a single function like .readText() or .readLines(). Let's look at specific examples.

\n\n

Reading an entire file

\n

The simplest way to read a text file is to use readText(). This method returns a string with the file's contents. Important: the file is automatically closed after reading.

\n\n
import java.io.File\n\nfun main() {\n    val content = File("example.txt").readText()\n    println(content)\n}
\n\n

If the file is large, it's better to read it line by line:

\n\n
val lines = File("example.txt").readLines()\nlines.forEach { line -> println(line) }
\n\n

And if you need to read it as a stream (for example, to process large logs):

\n\n
File("example.txt").useLines { lines ->\n    lines.forEach { line ->\n        // Process each line\n        println(line)\n    }\n}
\n\n

Notice useLines() — this is a function that guarantees the resource is closed after the block completes. It looks magical but works like try-with-resources in Java, only shorter.

\n\n

Writing to a file

\n

Writing data in Kotlin is also intuitive. Here are three options:

\n\n
// 1. Overwrite the file\nFile("output.txt").writeText("Hello, world!")\n\n// 2. Append to the end of the file\nFile("output.txt").appendText("New line\\n")\n\n// 3. Write a list of strings\nval list = listOf("line1", "line2", "line3")\nFile("output.txt").writeText(list.joinToString("\\n"))
\n\n

By the way, if you are working with binary data (images, archives), use writeBytes() and readBytes():

\n\n
val imageBytes = File("image.png").readBytes()\n// Process bytes...\nFile("copy.png").writeBytes(imageBytes)
\n\n

Managing the file system: creating, deleting, moving

\n\n

Kotlin doesn't reinvent the wheel, but it makes working with the file system more convenient. All operations are available through the java.io.File class with extensions.

\n\n

Creating directories

\n

To create a directory (and all parent directories if they don't exist):

\n\n
val dir = File("data/logs/2024")\nval created = dir.mkdirs() // Returns true if created\nprintln("Directory created: $created")
\n\n

Note: mkdir() creates only the last folder, while mkdirs() creates the entire chain.

\n\n

Checking existence and deleting

\n\n
val file = File("temp.txt")\nif (file.exists()) {\n    if (file.delete()) {\n        println("File deleted")\n    } else {\n        println("Could not delete")\n    }\n}\n\n// Recursive deletion of a directory\nFile("data").deleteRecursively()
\n\n

Be careful with deleteRecursively() — this is an irreversible operation. Double-check that you are deleting the right data.

\n\n

Moving and copying

\n\n
val source = File("old.txt")\nval target = File("new_dir/new.txt")\n\n// Moving (per                

Blogs

Book Recommendations