Skip to main content

Kotlin Writing Files

Introduction

Writing data to files is a fundamental part of many applications. Whether you're saving user preferences, logging information, or exporting data, knowing how to efficiently write to files in Kotlin is an essential skill. In this tutorial, we'll explore different methods to write data to files in Kotlin, from simple text files to more complex scenarios.

Kotlin provides several ways to handle file writing operations, building on Java's powerful I/O capabilities while adding its own syntax improvements and safety features. We'll cover everything from basic file writing to more advanced techniques using Kotlin's extension functions.

Basic File Writing in Kotlin

Writing Text Files

The simplest way to write to a text file in Kotlin is using the writeText() extension function provided by the Kotlin standard library.

kotlin
import java.io.File

fun main() {
val file = File("hello.txt")
file.writeText("Hello, Kotlin File I/O!")
println("File written successfully")
}

This creates a file named "hello.txt" and writes the string "Hello, Kotlin File I/O!" to it. If the file already exists, it will be overwritten.

Appending to Files

If you want to add content to an existing file rather than overwrite it, you can use the appendText() function:

kotlin
import java.io.File

fun main() {
val file = File("log.txt")

// First write
file.writeText("First line\n")

// Append more content
file.appendText("Second line\n")
file.appendText("Third line\n")

println("Content appended to file")

// Let's read and print the file content to verify
println("File content:")
println(file.readText())
}

Output:

Content appended to file
File content:
First line
Second line
Third line

Working with BufferedWriter

For better performance, especially when writing larger amounts of data, using a BufferedWriter is recommended:

kotlin
import java.io.File
import java.io.BufferedWriter

fun main() {
val file = File("buffered_output.txt")

file.bufferedWriter().use { writer ->
writer.write("First line\n")
writer.write("Second line\n")
writer.write("Third line\n")

// You can also write in a loop
for (i in 1..5) {
writer.write("Line number $i\n")
}
} // The use function automatically closes the writer when done

println("File written with BufferedWriter")
println("File content:")
println(file.readText())
}

Output:

File written with BufferedWriter
File content:
First line
Second line
Third line
Line number 1
Line number 2
Line number 3
Line number 4
Line number 5

The use function is particularly important as it ensures that resources are properly closed even if an exception occurs during writing.

Writing Binary Files

Sometimes you need to write binary data rather than text. Kotlin makes this easy as well:

kotlin
import java.io.File

fun main() {
val file = File("binary.data")
val byteArray = byteArrayOf(1, 2, 3, 4, 5, 10, 20, 30)

file.writeBytes(byteArray)
println("Binary data written to file (${byteArray.size} bytes)")

// Reading back the binary data
val readBytes = file.readBytes()
println("Read bytes: ${readBytes.joinToString()}")
}

Output:

Binary data written to file (8 bytes)
Read bytes: 1, 2, 3, 4, 5, 10, 20, 30

Creating Files in Specific Directories

To create files in specific directories, you need to ensure the directory exists first:

kotlin
import java.io.File

fun main() {
// Create a directory
val directory = File("output_directory")
if (!directory.exists()) {
directory.mkdir() // Creates single directory
// or directory.mkdirs() to create parent directories as needed
println("Directory created: ${directory.absolutePath}")
}

// Create a file in that directory
val file = File(directory, "file_in_directory.txt")
file.writeText("This file is in a specific directory")

println("File created at: ${file.absolutePath}")
}

Writing Data Line by Line

When dealing with collections of data, you might want to write each item on a separate line:

kotlin
import java.io.File

fun main() {
val lines = listOf(
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
"Sunday"
)

val file = File("days.txt")

// Method 1: Using writeText with line separators
file.writeText(lines.joinToString(separator = "\n"))

// Method 2: Using bufferedWriter
file.bufferedWriter().use { writer ->
lines.forEach { line ->
writer.write(line)
writer.newLine() // Platform-independent newline
}
}

println("Days written to file")
println("File content:")
println(file.readText())
}

Output:

Days written to file
File content:
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
Sunday

Real-World Example: Writing CSV Data

Let's create a more practical example: writing a list of products to a CSV file:

kotlin
import java.io.File

data class Product(val id: Int, val name: String, val price: Double, val quantity: Int)

fun main() {
val products = listOf(
Product(1, "Laptop", 1299.99, 5),
Product(2, "Smartphone", 799.99, 10),
Product(3, "Headphones", 149.99, 20),
Product(4, "Monitor", 349.99, 8),
Product(5, "Keyboard", 59.99, 15)
)

val csvFile = File("products.csv")

csvFile.bufferedWriter().use { writer ->
// Write header
writer.write("ID,Name,Price,Quantity")
writer.newLine()

// Write data
products.forEach { product ->
writer.write("${product.id},${product.name},${product.price},${product.quantity}")
writer.newLine()
}
}

println("Products exported to CSV file")
println("CSV content:")
println(csvFile.readText())
}

Output:

Products exported to CSV file
CSV content:
ID,Name,Price,Quantity
1,Laptop,1299.99,5
2,Smartphone,799.99,10
3,Headphones,149.99,20
4,Monitor,349.99,8
5,Keyboard,59.99,15

Error Handling When Writing Files

When working with files, it's important to handle potential errors:

kotlin
import java.io.File
import java.io.IOException

fun main() {
val file = File("/invalid_location/test.txt")

try {
file.writeText("This will cause an error")
} catch (e: IOException) {
println("Error writing to file: ${e.message}")

// Fallback: try writing to a valid location
val fallbackFile = File("fallback.txt")
fallbackFile.writeText("This is fallback content")
println("Wrote to fallback location: ${fallbackFile.absolutePath}")
}
}

Writing Files with PrintWriter

PrintWriter provides convenient methods for formatting output:

kotlin
import java.io.File
import java.io.PrintWriter

fun main() {
val file = File("formatted_output.txt")

PrintWriter(file).use { writer ->
writer.println("Line with newline")
writer.print("Line without newline ")
writer.print("continuation of the same line")
writer.println()

// Formatted output
writer.printf("Formatted number: %.2f\n", 10.12345)
writer.printf("Formatted string: %-10s | %5s\n", "left", "right")

// You can also write variables directly
val name = "Alice"
val age = 30
writer.println("Name: $name, Age: $age")
}

println("Formatted content written to file")
println("File content:")
println(file.readText())
}

Output:

Formatted content written to file
File content:
Line with newline
Line without newline continuation of the same line
Formatted number: 10.12
Formatted string: left | right
Name: Alice, Age: 30

Summary

In this tutorial, we've covered various ways to write data to files in Kotlin:

  1. Basic file writing with writeText() and appendText()
  2. Using BufferedWriter for efficient writing
  3. Writing binary data with writeBytes()
  4. Creating files in specific directories
  5. Writing collections of data line by line
  6. Creating CSV files (real-world example)
  7. Handling errors during file operations
  8. Using PrintWriter for formatted output

Kotlin's file I/O capabilities, built on top of Java's I/O system and enhanced with extension functions, make writing to files concise, safe, and flexible. The use function ensures resources are properly closed, preventing resource leaks in your applications.

Additional Resources and Exercises

Additional Resources

Exercises

  1. Log File Creator: Create a program that simulates a logging system, writing timestamp and message entries to a log file.

  2. Configuration File Writer: Write a program that creates a configuration file with key-value pairs.

  3. JSON File Writer: Use Kotlin's serialization library to write a complex object to a JSON file.

  4. File Copy Utility: Create a utility function that copies the contents from one file to another, showing progress updates.

  5. CSV to HTML Converter: Write a program that reads a CSV file and generates an HTML file with the data in a table format.

These exercises will help you practice file writing in different contexts and build practical applications using Kotlin's file I/O capabilities.



If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)