从 Kotlin 资源中读取文件:完整指南与示例

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

如何从 Kotlin 的 resources 文件夹中读取文本文件:分步教程

\n\n

你好,朋友!如果你曾经用 Kotlin 为 Android 编写过程序,或者只是创建过控制台应用程序,那么你肯定遇到过这个简单但棘手的问题:如何读取位于 resources 文件夹中的文本文件?看起来有什么复杂的呢?但如果你去 Stack Overflow 看看,"How to read a text file from resources in Kotlin?" 这个问题获得了数千次浏览。这说明问题确实存在。

\n\n

在本文中,我们将介绍 5 种可靠的方法来实现这一点。你将了解 javaClass 和 ClassLoader 之间的区别,如何避免 NullPointerException,以及如果你的项目是一个库而不是应用程序时该怎么办。开始吧!

\n\n

1. 准备工作:文件应该放在哪里?

\n

在读取文件之前,需要将其放在正确的位置。在标准的 Kotlin 项目(Gradle, Maven)中,资源文件夹通常位于此处:

\n\n
src/main/resources/
\n\n

对于测试,则是 src/test/resources/。如果你有一个 Android 项目,资源放在 src/main/res/raw/(但这有其自身的逻辑,下文会提到)。我们将专注于纯 Kotlin/JVM。

\n\n

让我们创建一个简单的文件 data.txt,内容如下:

\n
你好,世界!\n这些是来自资源的字符串。\nKotlin 太棒了。
\n\n

很好,工具准备好了。现在让我们看看如何打开它。

\n\n

2. 方法 #1:通过 javaClass 的经典方式

\n

最流行且直观的方法是使用 javaClass(这是 Kotlin 对 Java 中 getClass() 的封装)。

\n\n
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
\n\n

调用方式:

\n
fun main() {\n    val content = readFromResources("data.txt")\n    println(content)\n}
\n\n

输出将显示我们文件中的三行内容。简单而优雅。

\n\n

3. 方法 #2:使用 object 作为工具类

\n

如果你正在编写一个工具类,将逻辑提取到 object(单例)中会很方便。在 Kotlin 中,可以这样做:

\n\n
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 是一个单例,拥有自己的类。

\n\n

4. 方法 #3:作为 URL 读取(用于获取路径)

\n

有时你需要的不是文件内容,而是文件路径(例如,传递给其他库)。这时可以使用 getResource():

\n\n
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 将无法读取它。在这种情况下,最好始终使用流(

博客

书籍推荐