如何从Kotlin的资源中读取文本文件?

Ola*_*laf 66 kotlin

我想在Kotlin写一个Spek测试.测试应从该src/test/resources文件夹中读取HTML文件.怎么做?

class MySpec : Spek({

    describe("blah blah") {

        given("blah blah") {

            var fileContent : String = ""

            beforeEachTest {
                // How to read the file file.html in src/test/resources/html
                fileContent = ...  
            }

            it("should blah blah") {
                ...
            }
        }
    }
})
Run Code Online (Sandbox Code Playgroud)

JB *_*zet 90

val fileContent = MySpec::class.java.getResource("/html/file.html").readText()
Run Code Online (Sandbox Code Playgroud)

  • 对我来说这没用,我不得不把它改成`this :: class.java.classLoader.getResource("/ html/file.html").readText()` (26认同)
  • `val fileContent = javaClass.getResource("/ html/file.html").readText()`工作更短 (15认同)
  • 对我来说,这两个选项都适用于Android应用程序(注意其中一个中的额外`/`,必须在另一个中删除):`this :: class.java.getResource("/ html/file.html" ).readText()`和`this :: class.java.classLoader.getResource("html/file.html").readText()` (4认同)
  • 我无法让它工作,直到我在这里读到 `getResource` 和 `classLoader.getResource` 之间的区别:/sf/answers/462619391/ @SomaiahKumbera 前导斜杠使路径绝对,请参阅链接的帖子。 (3认同)
  • 奇怪的是我总是需要一个前导斜杠。例如,如果文件位于资源根目录中,您仍然必须将其引用为“/file.html” (2认同)

jho*_*ges 24

另一个略有不同的解

@Test
fun basicTest() {
    "/html/file.html".asResource {
        // test on `it` here...
        println(it)
    }

}

fun String.asResource(work: (String) -> Unit) {
    val content = this.javaClass::class.java.getResource(this).readText()
    work(content)
}
Run Code Online (Sandbox Code Playgroud)

  • 这是对扩展功能的严重滥用。加载文件不是 String 类关心的问题。 (8认同)
  • 正是在这种背景下。我不会使其在全球范围内可用或在测试类之外使用它。我在这里更多地认为它是一个映射函数。 (2认同)
  • @Ben 根据定义,使用扩展函数和扩展属性是一种滥用,因为它假装将成员添加到它没有内部访问权限的类中。如果您不喜欢它,请不要使用它。我们中的一些人专注于让我们的代码更简单,而不是担心面向对象的纯度。 (2认同)

Rus*_*ggs 15

不知道为什么这么难,但我发现的最简单的方法(无需引用特定的类)是:

fun getResourceAsText(path: String): String {
    return object {}.javaClass.getResource(path).readText()
}
Run Code Online (Sandbox Code Playgroud)

然后传入绝对URL,例如

val html = getResourceAsText("/www/index.html")
Run Code Online (Sandbox Code Playgroud)

  • 上面方法的缺点是,它为每次资源访问都创建了一个新对象。将伪对象存储在函数外部会更好。 (3认同)
  • 需要“{}”吗?为什么不只是“javaClass.getResource(path).readText()”? (2认同)
  • javaClass 必须根据文档在对象上调用 https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.jvm/java-class.html 如果它没有工作,那么去你的生活:) (2认同)
  • @RussellBriggs 说实话,我认为这并不重要。如果您进行磁盘访问,对象创建的性能实际上并不是问题! (2认同)

Ola*_*laf 12

略有不同的解决方案:

class MySpec : Spek({
    describe("blah blah") {
        given("blah blah") {

            var fileContent = ""

            beforeEachTest {
                html = this.javaClass.getResource("/html/file.html").readText()
            }

            it("should blah blah") {
                ...
            }
        }
    }
})
Run Code Online (Sandbox Code Playgroud)

  • 在`/src/test/resources`中创建测试输入文件后,`this.javaClass.getResource("/<test input filename>")`按预期工作。感谢上面的解决方案。 (2认同)

sai*_*pen 8

这是我更喜欢的方式:

fun getResourceText(path: String): String {
    return File(ClassLoader.getSystemResource(path).file).readText()
}
Run Code Online (Sandbox Code Playgroud)


Lu5*_*u55 7

使用谷歌番石榴库资源类

import com.google.common.io.Resources;

val fileContent: String = Resources.getResource("/html/file.html").readText()
Run Code Online (Sandbox Code Playgroud)

  • 如果找不到资源,Guave 会报告文件名,这很好 - 更好地进行故障排除 (2认同)

jiv*_*erg 6

val fileContent = javaClass.getResource("/html/file.html").readText()
Run Code Online (Sandbox Code Playgroud)


Ola*_*laf 6

private fun loadResource(file: String) = {}::class.java.getResource(file).readText()
Run Code Online (Sandbox Code Playgroud)


naX*_*aXa 5

Kotlin + Spring方式:

@Autowired
private lateinit var resourceLoader: ResourceLoader

fun load() {
    val html = resourceLoader.getResource("classpath:html/file.html").file
        .readText(charset = Charsets.UTF_8)
}
Run Code Online (Sandbox Code Playgroud)


min*_*lid 5

这个顶级 kotlin 函数在任何情况下都可以完成这项工作

fun loadResource(path: String): URL {
    return Thread.currentThread().contextClassLoader.getResource(path)
}
Run Code Online (Sandbox Code Playgroud)

或者如果你想要一个更强大的功能

fun loadResource(path: String): URL {
    val resource = Thread.currentThread().contextClassLoader.getResource(path)
    requireNotNull(resource) { "Resource $path not found" }
    return resource
}
Run Code Online (Sandbox Code Playgroud)