How to read a text file from resources in Kotlin?
KotlinKotlin Problem Overview
I want to write a Spek test in Kotlin. The test should read an HTML file from the src/test/resources
folder. How to do it?
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") {
...
}
}
}
})
Kotlin Solutions
Solution 1 - Kotlin
val fileContent = MySpec::class.java.getResource("/html/file.html").readText()
Solution 2 - Kotlin
No idea why this is so hard, but the simplest way I've found (without having to refer to a particular class) is:
fun getResourceAsText(path: String): String? =
object {}.javaClass.getResource(path)?.readText()
It returns null
if no resource with this name is found (as documented).
And then passing in an absolute URL, e.g.
val html = getResourceAsText("/www/index.html")!!
Solution 3 - Kotlin
another slightly different solution:
@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)
}
Solution 4 - Kotlin
A slightly different solution:
class MySpec : Spek({
describe("blah blah") {
given("blah blah") {
var fileContent = ""
beforeEachTest {
html = this.javaClass.getResource("/html/file.html").readText()
}
it("should blah blah") {
...
}
}
}
})
Solution 5 - Kotlin
Kotlin + Spring way:
@Autowired
private lateinit var resourceLoader: ResourceLoader
fun load() {
val html = resourceLoader.getResource("classpath:html/file.html").file
.readText(charset = Charsets.UTF_8)
}
Solution 6 - Kotlin
Using Google Guava library Resources class:
import com.google.common.io.Resources;
val fileContent: String = Resources.getResource("/html/file.html").readText()
Solution 7 - Kotlin
private fun loadResource(file: String) = {}::class.java.getResource(file).readText()
Solution 8 - Kotlin
val fileContent = javaClass.getResource("/html/file.html").readText()
Solution 9 - Kotlin
This is the way that I prefer to do it:
fun getResourceText(path: String): String {
return File(ClassLoader.getSystemResource(path).file).readText()
}
Solution 10 - Kotlin
this top-level kotlin function will do the job in any case
fun loadResource(path: String): URL {
return Thread.currentThread().contextClassLoader.getResource(path)
}
or if you want a more robust function
fun loadResource(path: String): URL {
val resource = Thread.currentThread().contextClassLoader.getResource(path)
requireNotNull(resource) { "Resource $path not found" }
return resource
}
Solution 11 - Kotlin
FYI: In all the above cases. getResource()
is unsafe way of using nullable.
Haven't tried locally but I prefer this way:
fun readFile(resourcePath: String) = String::class.java.getResource(resourcePath)?.readText() ?: "<handle default. or handle custom exception>"
Or even as custom datatype function
private fun String.asResource() = this::class.java.getResource(resourcePath)?.readText() ?: "<handle default. or handle custom exception>"
and then you can call directly on path like:
// For suppose
val path = "/src/test/resources"
val content = path.asResource()
Solution 12 - Kotlin
You might find the File class useful:
import java.io.File
fun main(args: Array<String>) {
val content = File("src/main/resources/input.txt").readText()
print(content)
}