Kotlin'deki kaynaklardan bir metin dosyası nasıl okunur?


103

Kotlin'de bir Spek testi yazmak istiyorum. Test, src/test/resourcesklasörden bir HTML dosyası okumalıdır . Nasıl yapılır?

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

Yanıtlar:


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

32
Benim için bu işe yaramadı, değiştirmem gerekiyorduthis::class.java.classLoader.getResource("/html/file.html").readText()
pavlos163

4
Benim için her iki seçenek de bir Android uygulamasında çalıştı /(bunlardan birinde fazladan olana dikkat edin , diğerinde kaldırılması gerekir): this::class.java.getResource("/html/file.html").readText()vethis::class.java.classLoader.getResource("html/file.html").‌​readText()
Franco

25
val fileContent = javaClass.getResource("/html/file.html").readText()işi daha da kısalıyor
Frank Neblung

1
İşin garibi, her zaman bir satır başı çizgisine ihtiyacım var. Örneğin, dosya kaynaklar kök dizinindeyse, ona yine de "/file.html" olarak başvurmanız gerekir
Somaiah Kumbera

32

Bunun neden bu kadar zor olduğu hakkında hiçbir fikrim yok, ama bulduğum en basit yol (belirli bir sınıfa atıfta bulunmak zorunda kalmadan):

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

Ve sonra mutlak bir URL geçirin, ör.

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

edilir {}gerekli? Neden sadece değil javaClass.getResource(path).readText()?
andrewgazelka

2
javaClass docs göre bir nesne üzerinde çağrılmalıdır kotlinlang.org/api/latest/jvm/stdlib/kotlin.jvm/java-class.html o :) sonra ya hayat için gitmek olmadan çalışırsa
Russell Briggs

3
Yukarıdaki yöntemin bir dezavantajı, her kaynak erişimi için yeni bir nesne oluşturmasıdır. Kukla nesneyi işlevin dışında saklamak daha iyi olur.
Russell Briggs

@RussellBriggs tbh Bunun önemli olduğunu sanmıyorum. Disk erişimi yaparsanız, bir nesne oluşturmanın performansı gerçekten bir sorun değildir!
Qw3ry

29

biraz farklı bir çözüm daha:

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

Bir uzantı işlevinin güzel kullanımı! Ama burada neden bir lambda işlevi kullanıyorsunuz? Bu bana pek mantıklı gelmiyor. Üstelik bu thiskısım benim için işe yaramadı. Bu nedenle aşağıdakileri tavsiye ederim:fun String.asResource(): URL? = object {}.javaClass.getResource(this)
Qw3ry

Dosyayı açıkladığınız ve ardından o dosyanın içeriği üzerinde çalıştığınız bu yöntem üzerinde çalışmayı seviyorum. Kişisel tercih sanırım. thisyukarıdaki örnekte string nesnesine atıfta bulunulmaktadır.
jhodges

1
bu, uzantı işlevinin kötüye kullanılmasıdır. Dosyaları yüklemek, String sınıfının bir sorunu değildir.
Ben

bu bağlamda. bunu küresel olarak kullanıma sunmam veya test sınıflarının dışında kullanmam. Bunu burada daha çok bir haritalama işlevi olarak görüyorum.
jhodges

13

Biraz farklı bir çözüm:

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

            var fileContent = ""

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

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

Nedense bu benim için işe yaramadı. Sadece açıkça sınıf işe yaradı. Sadece diğerleri için ekliyor. Bunun tornadofx ile bir ilgisi olduğunu düşünüyorum
nmu

Bir test girdi dosyasını oluşturduktan sonra /src/test/resources, this.javaClass.getResource("/<test input filename>")beklendiği gibi çalıştı. Yukarıdaki çözüm için teşekkürler.
jkwuc89

fileContent String değilse ve herhangi bir sahte nesne oluşturmayacaksam ne yapmalıyım?
minizibi

1
Burada yolun önündeki eğik çizgi zorunlu görünürken, Java'da genellikle bunu ihmal ederim.
cakraww

6

Kotlin + Bahar yolu:

@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

Google Guava kütüphane Kaynakları sınıfını kullanarak :

import com.google.common.io.Resources;

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

Kaynak bulunmazsa Guave'nin bir dosya adı bildirmesi güzel - sorun giderme için çok daha iyi
Nishi

2

Bunu yapmayı tercih ettiğim yol bu:

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

0

File sınıfını yararlı bulabilirsiniz:

import java.io.File

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

5
Bu cevap yanıltıcıdır. Bu bir "kaynak" yüklemez, ancak dosyayı sınıf yolu yerine doğrudan dosya sisteminden yükler. Jar dosyasından yüklemek yerine mevcut olmayan dosyalara başvurmaya çalışacağınız için uygulama birleştirildikten sonra artık çalışmayacaktır.
Ben

@ben Yorumunuz için teşekkürler. Soru, kotlin Spek testinde kaynaktan dosya okumakla ilgiliydi.
Krzysztof Ziomek
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.