Bagaimana cara membaca file teks dari sumber daya di Kotlin?


97

Saya ingin menulis tes Spek di Kotlin. Tes harus membaca file HTML dari src/test/resourcesfolder. Bagaimana cara melakukannya?

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") {
                ...
            }
        }
    }
})

Jawaban:


116
val fileContent = MySpec::class.java.getResource("/html/file.html").readText()

30
Bagi saya ini tidak berhasil, saya harus mengubahnya menjadithis::class.java.classLoader.getResource("/html/file.html").readText()
pavlos163

4
Bagi saya, kedua opsi ini berfungsi di aplikasi Android (perhatikan tambahan /di salah satunya, yang harus dihapus di opsi lain): this::class.java.getResource("/html/file.html").readText()danthis::class.java.classLoader.getResource("html/file.html").‌​readText()
Franco

20
val fileContent = javaClass.getResource("/html/file.html").readText()melakukan pekerjaan lebih pendek lagi
Frank Neblung

1
Anehnya, saya selalu membutuhkan garis miring. Misalnya, jika file ada di direktori root resource, Anda masih harus merujuknya sebagai "/file.html"
Somaiah Kumbera

28

solusi lain yang sedikit berbeda:

@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)
}

Penggunaan yang bagus dari fungsi ekstensi! Tetapi mengapa Anda menggunakan fungsi lambda di sini? Itu tidak masuk akal bagi saya. Selain itu, thisbagian itu tidak berhasil untuk saya. Karena itu saya merekomendasikan yang berikut ini:fun String.asResource(): URL? = object {}.javaClass.getResource(this)
Qw3ry

Saya suka metode mengerjakannya di mana Anda mendeklarasikan file, lalu mengerjakan konten file itu. Preferensi pribadi saya kira. thispada contoh di atas mengacu pada objek string.
jhodges

itulah penyalahgunaan fungsi ekstensi yang mengerikan. Memuat file bukanlah urusan kelas String.
Ben

itu dalam konteks ini. saya tidak akan membuat ini tersedia secara global atau menggunakannya di luar kelas tes. Saya menganggapnya lebih sebagai fungsi pemetaan di sini.
jhodges

28

Tidak tahu mengapa ini sangat sulit, tetapi cara paling sederhana yang saya temukan (tanpa harus merujuk ke kelas tertentu) adalah:

fun getResourceAsText(path: String): String {
    return object {}.javaClass.getResource(path).readText()
}

Dan kemudian memasukkan URL absolut, mis

val html = getResourceAsText("/www/index.html")

yang {}diperlukan? Kenapa tidak javaClass.getResource(path).readText()?
andrewgazelka

2
javaClass harus dipanggil pada sebuah objek sesuai dengan dokumen kotlinlang.org/api/latest/jvm/stdlib/kotlin.jvm/java-class.html Jika berfungsi tanpa maka go for ya life :)
Russell Briggs

3
Satu kelemahan dari metode di atas adalah membuat objek baru untuk setiap akses sumber daya. Akan lebih baik untuk menyimpan objek dummy di luar fungsi.
Russell Briggs

@RussellBriggs tbh Saya rasa itu tidak terlalu penting. Kinerja pembuatan objek sebenarnya tidak menjadi masalah jika Anda melakukan akses disk!
Qw3ry

13

Solusi yang sedikit berbeda:

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

            var fileContent = ""

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

            it("should blah blah") {
                ...
            }
        }
    }
})

Untuk beberapa alasan ini tidak berhasil untuk saya. Hanya memanggil kelas secara eksplisit yang berhasil. Hanya menambahkan untuk orang lain. Saya pikir itu ada hubungannya dengan tornadofx
nmu

Setelah membuat file input tes /src/test/resources, this.javaClass.getResource("/<test input filename>")bekerja seperti yang diharapkan. Terima kasih atas solusi di atas.
jkwuc89

apa yang harus dilakukan, jika fileContent bukan String dan saya tidak akan membuat objek dummy?
minizibi

1
garis miring sebelum jalur tampaknya wajib di sini, sedangkan di Jawa saya biasanya menghilangkannya.
cakraww

6

Kotlin + Cara musim semi:

@Autowired
private lateinit var resourceLoader: ResourceLoader

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

5
val fileContent = javaClass.getResource("/html/file.html").readText()

5
private fun loadResource(file: String) = {}::class.java.getResource(file).readText()

4

Menggunakan kelas Sumber Daya pustaka Google Guava :

import com.google.common.io.Resources;

val fileContent: String = Resources.getResource("/html/file.html").readText()

bagus bahwa Guave melaporkan nama file jika sumber daya tidak ditemukan - jauh lebih baik untuk pemecahan masalah
Nishi

2

Inilah cara yang saya lebih suka melakukannya:

fun getResourceText(path: String): String {
    return File(ClassLoader.getSystemResource(path).file).readText()
}

0

Anda mungkin menemukan kelas File berguna:

import java.io.File

fun main(args: Array<String>) {
  val content = File("src/main/resources/input.txt").readText()
  print(content)
} 

3
Jawaban ini menyesatkan. Itu tidak memuat "resource", tetapi memuat file langsung dari sistem file, bukan dari classpath. Ini tidak akan berfungsi lagi setelah aplikasi dirakit karena Anda akan mencoba merujuk ke file yang tidak ada, alih-alih memuatnya dari file jar.
Ben

@ben Terima kasih atas komentar Anda. Pertanyaannya adalah tentang membaca file dari sumber daya di tes Spek kotlin.
Krzysztof Ziomek
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.