File Handling
Read and write files, perform file operations, and manage directories in Kotlin JVM applications
Read
Write
Operations
Directories
1Reading Files
Kotlin builds on Java's I/O APIs and adds convenient extensions in kotlin.io. The java.io.File class and readText(), readLines(), and bufferedReader() extensions make reading files concise and safe.
Read entire file as String
readText()import java.io.File
fun main() {
val file = File("notes.txt")
if (file.exists()) {
val content = file.readText()
println(content)
} else {
println("File not found")
}
}
Read file line by line
readLines() and forEachLineimport java.io.File
fun main() {
val file = File("users.txt")
// Read all lines into a List<String>
val lines = file.readLines()
lines.forEach { println(it) }
// Memory-efficient — process one line at a time
file.forEachLine { line ->
println("Line: $line")
}
}
BufferedReader with use()
bufferedReader() — large filesimport java.io.File
fun countWords(filename: String): Int {
val file = File(filename)
return file.bufferedReader().use { reader ->
reader.lineSequence()
.flatMap { it.split("\\s+".toRegex()).asSequence() }
.count { it.isNotBlank() }
}
}
Reading methods comparison
| Method | Returns | Best for |
readText() | Full file as String | Small text files, config files |
readBytes() | ByteArray | Binary files, images |
readLines() | List<String> | All lines loaded into memory |
forEachLine { } | Unit (callback per line) | Large files — streaming |
bufferedReader() | BufferedReader | Fine-grained control, large files |
Safe read with exception handlingimport java.io.File
import java.io.IOException
fun readConfig(path: String): String? {
return try {
File(path).readText()
} catch (e: IOException) {
println("Failed to read file: ${e.message}")
null
}
}
Always use use { }
Wrap streams and readers in .use { } to auto-close resources — see Finally Block.
2Writing Files
Kotlin extensions writeText(), appendText(), and printWriter() simplify writing strings and lines to files.
Write text to a file
writeText() — overwrites fileimport java.io.File
fun main() {
val file = File("output.txt")
file.writeText("Hello, Kotlin File I/O!")
println("File written successfully")
}
Append to existing file
appendText()import java.io.File
fun main() {
val logFile = File("app.log")
logFile.appendText("App started\n")
logFile.appendText("User logged in\n")
logFile.appendText("App closed\n")
}
Write lines and bytes
writeLines() and writeBytes()import java.io.File
fun main() {
val file = File("data.txt")
val lines = listOf("Line 1", "Line 2", "Line 3")
file.writeLines(lines)
val bytes = byteArrayOf(0x48, 0x65, 0x6C, 0x6C, 0x6F) // "Hello"
File("binary.dat").writeBytes(bytes)
}
BufferedWriter for large output
bufferedWriter()import java.io.File
fun writeReport(filename: String, entries: List<String>) {
File(filename).bufferedWriter().use { writer ->
writer.write("=== Report ===\n")
entries.forEach { entry ->
writer.write("$entry\n")
}
writer.write("=== End ===\n")
}
}
fun main() {
writeReport("report.txt", listOf("Entry A", "Entry B", "Entry C"))
}
| Method | Behavior |
writeText(text) | Overwrites entire file with string |
appendText(text) | Adds to end of file (creates if missing) |
writeLines(lines) | Writes list of lines with line separators |
writeBytes(bytes) | Writes raw byte array |
printWriter() | Formatted output with PrintWriter |
Character encoding: Pass charset explicitly when needed — file.readText(Charsets.UTF_8) and file.writeText(text, Charsets.UTF_8). UTF-8 is the default on most platforms.
3File Operations
Beyond read/write, Kotlin (via java.io.File) supports checking existence, copying, moving, deleting, and inspecting file metadata.
Check file properties
File metadataimport java.io.File
fun inspectFile(path: String) {
val file = File(path)
println("Exists: ${file.exists()}")
println("Is file: ${file.isFile}")
println("Is directory: ${file.isDirectory}")
println("Name: ${file.name}")
println("Extension: ${file.extension}")
println("Size: ${file.length()} bytes")
println("Absolute path: ${file.absolutePath}")
println("Last modified: ${file.lastModified()}")
println("Can read: ${file.canRead()}")
println("Can write: ${file.canWrite()}")
}
fun main() {
inspectFile("sample.txt")
}
Copy, move, and delete
kotlin.io extensionsimport java.io.File
fun main() {
val source = File("original.txt")
source.writeText("Original content")
// Copy file
source.copyTo(File("copy.txt"), overwrite = true)
// Rename / move
File("copy.txt").renameTo(File("renamed.txt"))
// Delete
val deleted = File("renamed.txt").delete()
println("Deleted: $deleted")
}
Create and delete files
createNewFile and deleteRecursivelyimport java.io.File
fun main() {
val newFile = File("temp.txt")
val created = newFile.createNewFile()
println("Created: $created") // true if new file was created
newFile.writeText("Temporary data")
newFile.delete()
// Delete directory and all contents
// File("old_folder").deleteRecursively()
}
Common file operations
| Operation | Method |
| Check exists | file.exists() |
| Copy | source.copyTo(target, overwrite) |
| Move/rename | file.renameTo(newFile) |
| Delete file | file.delete() |
| Delete tree | file.deleteRecursively() |
| Create file | file.createNewFile() |
| File size | file.length() |
| Walk tree | file.walkTopDown(), walkBottomUp() |
Walk file treeimport java.io.File
fun listAllFiles(directory: File) {
directory.walkTopDown()
.filter { it.isFile }
.forEach { file ->
println("${file.absolutePath} (${file.length()} bytes)")
}
}
NIO Path API
For advanced I/O, Java NIO java.nio.file.Files and Path offer atomic moves, symbolic links, and watch services — useful in server and desktop apps.
4Working with Directories
Directories organize files into a hierarchy. Kotlin provides extensions to create directories, list contents, and traverse folder trees.
Create directories
mkdir and mkdirsimport java.io.File
fun main() {
// Create single directory
val dir = File("myapp")
dir.mkdir()
// Create nested directories (parent + child)
val nested = File("myapp/logs/2026")
nested.mkdirs()
println("Created: ${nested.exists()}") // true
}
List directory contents
listFiles()import java.io.File
fun listDirectory(path: String) {
val dir = File(path)
if (!dir.isDirectory) {
println("Not a directory")
return
}
dir.listFiles()?.forEach { file ->
val type = if (file.isDirectory) "[DIR]" else "[FILE]"
println("$type ${file.name}")
}
}
fun main() {
listDirectory("myapp")
}
Kotlin list extensions
listFiles, walk, filter extensionsimport java.io.File
fun exploreDirectory(path: String) {
val dir = File(path)
// Only files
val files = dir.listFiles { f -> f.isFile }
files?.forEach { println("File: ${it.name}") }
// Only .txt files
val txtFiles = dir.listFiles { f -> f.extension == "txt" }
txtFiles?.forEach { println("TXT: ${it.name}") }
// Recursive walk — all files
dir.walkTopDown()
.maxDepth(3)
.filter { it.isFile && it.extension == "log" }
.forEach { println("Log: ${it.absolutePath}") }
}
Directory operations reference
| Task | Method |
| Create one level | File("dir").mkdir() |
| Create nested paths | File("a/b/c").mkdirs() |
| List contents | dir.listFiles() |
| Filter listing | dir.listFiles { f -> condition } |
| Recursive traversal | dir.walkTopDown() |
| Delete directory tree | dir.deleteRecursively() |
| Resolve child path | File(dir, "child.txt") or dir.resolve("child.txt") |
Practical example — organize downloads
Create project folder structureimport java.io.File
fun createProjectStructure(basePath: String) {
val base = File(basePath)
val folders = listOf("src/main/kotlin", "src/test/kotlin", "resources", "logs")
folders.forEach { path ->
File(base, path).mkdirs()
}
File(base, "README.md").writeText("# My Project\n")
File(base, "logs/.gitkeep").writeText("")
println("Project structure created at ${base.absolutePath}")
}
fun main() {
createProjectStructure("demo-project")
}
Android note: On Android, app-private storage uses context.filesDir and context.cacheDir — not raw filesystem paths. Shared storage requires scoped storage APIs (MediaStore, SAF). This tutorial focuses on JVM/desktop/CLI Kotlin.
5Summary Cheatsheet
| Topic | Key Takeaway |
| Reading Files | readText(), readLines(), forEachLine, bufferedReader().use { } |
| Writing Files | writeText(), appendText(), writeLines(), writeBytes() |
| File Operations | exists(), copyTo(), delete(), walkTopDown() |
| Directories | mkdir(), mkdirs(), listFiles(), deleteRecursively() |
| Best practice | Use use { } for streams; handle IOException |
| Package | kotlin.io extensions on java.io.File |
| Next lesson | Coroutines |