Comment lire un fichier texte à partir de ressources dans Kotlin?


94

Je veux écrire un test Spek à Kotlin. Le test doit lire un fichier HTML à partir du src/test/resourcesdossier. Comment faire?

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

Réponses:


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

30
Pour moi, cela n'a pas fonctionné, j'ai dû le changer enthis::class.java.classLoader.getResource("/html/file.html").readText()
pavlos163

4
Pour moi, ces deux options fonctionnaient dans une application Android (notez le supplément /dans l'une d'elles, qui doit être supprimé dans l'autre): this::class.java.getResource("/html/file.html").readText()etthis::class.java.classLoader.getResource("html/file.html").‌​readText()
Franco

19
val fileContent = javaClass.getResource("/html/file.html").readText()fait le travail encore plus court
Frank Neblung

28

une autre solution légèrement différente:

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

Bonne utilisation d'une fonction d'extension! Mais pourquoi utilisez-vous une fonction lambda ici? Cela n'a pas beaucoup de sens pour moi. De plus, la thispièce n'a pas fonctionné pour moi. Je recommande donc ce qui suit:fun String.asResource(): URL? = object {}.javaClass.getResource(this)
Qw3ry

J'aime cette méthode de travail où vous déclarez le fichier, puis travaillez sur le contenu de ce fichier. Préférence personnelle je suppose. thisdans l'exemple ci-dessus fait référence à l'objet string.
jhodges

c'est un terrible abus de la fonction d'extension. Le chargement de fichiers n'est pas une préoccupation de la classe String.
Ben le

c'est dans ce contexte. Je ne le rendrais pas disponible dans le monde entier ou ne l'utiliserais pas en dehors des classes de test. Je le considère plus comme une fonction de cartographie ici.
jhodges

25

Je ne sais pas pourquoi c'est si difficile, mais le moyen le plus simple que j'ai trouvé (sans avoir à faire référence à une classe particulière) est:

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

Et puis en passant une URL absolue, par exemple

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

est {}nécessaire? Pourquoi pas juste javaClass.getResource(path).readText()?
andrewgazelka

1
javaClass doit être appelé sur un objet selon la documentation kotlinlang.org/api/latest/jvm/stdlib/kotlin.jvm/java-class.html Si cela fonctionne sans alors allez-y pour votre vie :)
Russell Briggs

3
Un inconvénient de la méthode ci-dessus est qu'elle crée un nouvel objet pour chaque accès aux ressources. Il serait préférable de stocker l'objet factice en dehors de la fonction.
Russell Briggs

@RussellBriggs tbh Je ne pense pas que cela compte beaucoup. La performance de la création d'un objet n'est pas vraiment un problème si vous effectuez un accès disque!
Qw3ry

13

Une solution légèrement différente:

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

            var fileContent = ""

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

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

Pour une raison quelconque, cela n'a pas fonctionné pour moi. Seulement appeler explicitement la classe a fonctionné. Juste ajouter pour les autres. Je pense que cela a quelque chose à voir avec tornadofx
nmu

Après avoir créé un fichier d'entrée de test dans /src/test/resources, a this.javaClass.getResource("/<test input filename>")fonctionné comme prévu. Merci pour la solution ci-dessus.
jkwuc89

que faire, si fileContent n'est pas String et que je ne créerai aucun objet factice?
minizibi

1
la barre oblique avant le chemin semble obligatoire ici, alors qu'en Java, je l'omets généralement.
cakraww

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

5

Voie Kotlin + Spring:

@Autowired
private lateinit var resourceLoader: ResourceLoader

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

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

4

Utilisation de la classe Ressources de la bibliothèque Google Guava :

import com.google.common.io.Resources;

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

c'est bien que Guave signale un nom de fichier si la ressource n'est pas trouvée - beaucoup mieux pour le dépannage
Nishi

0

Vous pourriez trouver la classe File utile:

import java.io.File

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

3
Cette réponse est trompeuse. Cela ne charge pas une "ressource" mais charge le fichier directement à partir du système de fichiers, au lieu du chemin de classe. Cela ne fonctionnera plus une fois l'application assemblée, car vous essaierez de faire référence à des fichiers inexistants, au lieu de les charger à partir du fichier jar.
Ben le

@ben Merci pour votre commentaire. La question portait sur la lecture du fichier à partir de la ressource dans le test kotlin Spek.
Krzysztof Ziomek le

0

C'est comme ça que je préfère le faire:

fun getResourceText(path: String): String {
    return File(ClassLoader.getSystemResource(path).file).readText()
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.