How to Read a Text File from the Resources Folder in Kotlin: A Step-by-Step Tutorial
\n\nHello, friend! If you've ever written in Kotlin for Android or simply created a console application, you've likely encountered a simple but tricky task: how to read a text file located in the resources folder? It seems simple, right? But if you look at Stack Overflow, the question "How to read a text file from resources in Kotlin?" gets thousands of views. So, the problem is real.
In this article, we'll cover 5 reliable ways to do this. You'll learn the difference between javaClass and ClassLoader, how to avoid a NullPointerException, and what to do if your project is a library, not an application. Let's go!
1. Preparation: Where to Put the File?
\nBefore reading, you need to put the file in the right place. In a standard Kotlin project (Gradle, Maven), the resources folder is usually located here:
\n\nsrc/main/resources/\n\nFor tests — src/test/resources/. If you have an Android project, resources are placed in src/main/res/raw/ (but that has its own logic, more on that below). We'll focus on pure Kotlin/JVM.
Let's create a simple file data.txt with the content:
Hello, world!\nThese are lines from resources.\nKotlin rocks.\n\nGreat, the tool is ready. Now let's see how to open it.
\n\n2. Method #1: The Classic Way via javaClass
\nThe most popular and intuitive way is to use javaClass (this is Kotlin's wrapper over getClass() in Java).
import java.io.File\n\nfun readFromResources(fileName: String): String {\n val inputStream = this::class.java.classLoader?.getResourceAsStream(fileName)\n ?: throw IllegalArgumentException("File $fileName not found in resources")\n return inputStream.bufferedReader().readText()\n}\n\nBreakdown:
\n- \n
this::class.java— gets the Java class of the current object. \n .classLoader— gets the ClassLoader. \n getResourceAsStream(fileName)— opens a stream. \n - The Elvis operator
?:throws an exception if the file is not found. \n
Call it:
\nfun main() {\n val content = readFromResources("data.txt")\n println(content)\n}\n\nThe output will show the three lines from our file. Simple and elegant.
\n\n3. Method #2: Using an Object for Utilities
\nIf you're writing a utility class, it's convenient to put the logic in an object (singleton). In Kotlin, this is done like this:
object ResourceReader {\n fun readText(fileName: String): String {\n val stream = ResourceReader::class.java.classLoader\n .getResourceAsStream(fileName)\n ?: throw FileNotFoundException("Resource $fileName not found")\n return stream.bufferedReader().readText()\n }\n}\n\n// Usage:\nfun main() {\n val text = ResourceReader.readText("config.json")\n println(text)\n}\n\nNote: we use ResourceReader::class.java — this works because an object is a singleton that has a class.
4. Method #3: Reading as a URL (to Get the Path)
\nSometimes you need not the content, but the path to the file (for example, to pass to another library). In that case, use getResource():
fun getResourcePath(fileName: String): String {\n val url = this::class.java.classLoader.getResource(fileName)\n ?: throw RuntimeException("Resource $fileName not found")\n return url.path\n}\n\nBut be careful: if the project is packaged into a JAR, url.path may point inside the archive, and File won't be able to read it. In this case, it's better to always use a stream (