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.