如何从 Kotlin 的 resources 文件夹中读取文本文件:分步教程
\n\n你好,朋友!如果你曾经用 Kotlin 为 Android 编写过程序,或者只是创建过控制台应用程序,那么你肯定遇到过这个简单但棘手的问题:如何读取位于 resources 文件夹中的文本文件?看起来有什么复杂的呢?但如果你去 Stack Overflow 看看,"How to read a text file from resources in Kotlin?" 这个问题获得了数千次浏览。这说明问题确实存在。
在本文中,我们将介绍 5 种可靠的方法来实现这一点。你将了解 javaClass 和 ClassLoader 之间的区别,如何避免 NullPointerException,以及如果你的项目是一个库而不是应用程序时该怎么办。开始吧!
1. 准备工作:文件应该放在哪里?
\n在读取文件之前,需要将其放在正确的位置。在标准的 Kotlin 项目(Gradle, Maven)中,资源文件夹通常位于此处:
\n\nsrc/main/resources/\n\n对于测试,则是 src/test/resources/。如果你有一个 Android 项目,资源放在 src/main/res/raw/(但这有其自身的逻辑,下文会提到)。我们将专注于纯 Kotlin/JVM。
让我们创建一个简单的文件 data.txt,内容如下:
你好,世界!\n这些是来自资源的字符串。\nKotlin 太棒了。\n\n很好,工具准备好了。现在让我们看看如何打开它。
\n\n2. 方法 #1:通过 javaClass 的经典方式
\n最流行且直观的方法是使用 javaClass(这是 Kotlin 对 Java 中 getClass() 的封装)。
import java.io.File\n\nfun readFromResources(fileName: String): String {\n val inputStream = this::class.java.classLoader?.getResourceAsStream(fileName)\n ?: throw IllegalArgumentException("文件 $fileName 在资源中未找到")\n return inputStream.bufferedReader().readText()\n}\n\n代码解析:
\n- \n
this::class.java— 获取当前对象的 Java 类。 \n .classLoader— 获取 ClassLoader(类加载器)。 \n getResourceAsStream(fileName)— 打开一个流。 \n - Elvis 运算符
?:在文件不存在时抛出异常。 \n
调用方式:
\nfun main() {\n val content = readFromResources("data.txt")\n println(content)\n}\n\n输出将显示我们文件中的三行内容。简单而优雅。
\n\n3. 方法 #2:使用 object 作为工具类
\n如果你正在编写一个工具类,将逻辑提取到 object(单例)中会很方便。在 Kotlin 中,可以这样做:
object ResourceReader {\n fun readText(fileName: String): String {\n val stream = ResourceReader::class.java.classLoader\n .getResourceAsStream(fileName)\n ?: throw FileNotFoundException("资源 $fileName 未找到")\n return stream.bufferedReader().readText()\n }\n}\n\n// 使用方式:\nfun main() {\n val text = ResourceReader.readText("config.json")\n println(text)\n}\n\n请注意:我们使用了 ResourceReader::class.java — 这是可行的,因为 object 是一个单例,拥有自己的类。
4. 方法 #3:作为 URL 读取(用于获取路径)
\n有时你需要的不是文件内容,而是文件路径(例如,传递给其他库)。这时可以使用 getResource():
fun getResourcePath(fileName: String): String {\n val url = this::class.java.classLoader.getResource(fileName)\n ?: throw RuntimeException("资源 $fileName 未找到")\n return url.path\n}\n\n但要小心:如果项目被打包成 JAR 文件,url.path 可能指向归档文件内部,File 将无法读取它。在这种情况下,最好始终使用流(