Kotlin의 리소스에서 텍스트 파일을 읽는 방법은 무엇입니까?


97

Kotlin에서 Spek 테스트를 작성하고 싶습니다. 테스트는 src/test/resources폴더 에서 HTML 파일을 읽어야 합니다. 어떻게하나요?

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

답변:


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

30
나를 위해이 작동하지 않았다, 나는로 변경했다this::class.java.classLoader.getResource("/html/file.html").readText()
— pavlos163

4
나에게이 두 가지 옵션은 모두 Android 앱에서 작동했습니다 ( /하나의 추가 옵션 은 다른 하나에서는 제거되어야 함). this::class.java.getResource("/html/file.html").readText()그리고this::class.java.classLoader.getResource("html/file.html").‌​readText()
— Franco

20
val fileContent = javaClass.getResource("/html/file.html").readText()작업도 짧은 않습니다
— 프랭크 Neblung

1
이상하게도 나는 항상 선행 슬래시가 필요합니다. 예를 들어 파일이 리소스 루트 디렉토리에있는 경우에도 "/file.html"로 참조해야합니다.
— Somaiah Kumbera

28

또 다른 약간 다른 솔루션 :

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

확장 기능의 좋은 사용! 그런데 왜 여기서 람다 함수를 사용합니까? 그것은 나에게별로 의미가 없습니다. 게다가 그 this부분은 나를 위해 작동하지 않았습니다. 따라서 다음을 추천합니다.fun String.asResource(): URL? = object {}.javaClass.getResource(this)
— Qw3ry

파일을 선언 한 다음 해당 파일의 내용을 작업하는이 방법이 마음에 듭니다. 개인적 선호도 같아요. this위의 예에서 문자열 개체를 참조합니다.
— jhodges 19

확장 기능의 끔찍한 남용입니다. 파일로드는 String 클래스의 문제가 아닙니다.
— Ben

이 맥락에 있습니다. 나는 이것을 전 세계적으로 사용하거나 테스트 클래스 외부에서 사용하지 않을 것입니다. 여기서는 매핑 기능에 더 가깝다고 생각합니다.
— jhodges

28

이것이 왜 그렇게 어려운지 모르겠지만 내가 찾은 가장 간단한 방법은 (특정 클래스를 참조하지 않고도) 다음과 같습니다.

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

그런 다음 절대 URL을 전달합니다. 예 :

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

되어 {}필요? 왜 안돼 javaClass.getResource(path).readText()?
— andrewgazelka

2
javaClass는 docs kotlinlang.org/api/latest/jvm/stdlib/kotlin.jvm/java-class.html 에 따라 객체에서 호출되어야합니다. 만약 그것이없이 작동한다면 당신의 삶을 위해 가십시오 :)
— Russell Briggs

3
위의 방법의 한 가지 단점은 모든 리소스 액세스에 대해 새 개체를 생성한다는 것입니다. 함수 외부에 더미 객체를 저장하는 것이 좋습니다.
— Russell Briggs

@RussellBriggs tbh 나는 그다지 중요하지 않다고 생각합니다. 디스크 액세스를 수행하는 경우 개체 생성 성능은 실제로 문제가되지 않습니다!
— Qw3ry

13

약간 다른 솔루션 :

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

            var fileContent = ""

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

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

어떤 이유로 이것은 나를 위해 작동하지 않았습니다. 클래스를 명시 적으로 호출하는 것만 작동했습니다. 다른 사람을 위해 추가하는 것뿐입니다. 나는 그것이 tornadofx와 관련이 있다고 생각합니다
— nmu

에 테스트 입력 파일을 생성 한 후 /src/test/resources, this.javaClass.getResource("/<test input filename>")같은 예상했다. 위의 솔루션에 감사드립니다.
— jkwuc89

fileContent가 String이 아니고 더미 개체를 만들지 않는 경우 어떻게해야합니까?
— minizibi

1
여기서는 경로 앞의 슬래시가 필수 인 것처럼 보이지만 Java에서는 일반적으로 생략합니다.
— cakraww

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

5

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

Google Guava 라이브러리 리소스 클래스 사용 :

import com.google.common.io.Resources;

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

그것은 자원이 발견되지 않는 경우 Guave 파일 이름을보고 있다는 좋은 - 더 나은 문제 해결을 위해
— 니시

1

이것이 내가 선호하는 방법입니다.

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

0

File 클래스가 유용 할 수 있습니다.

import java.io.File

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

3
이 대답은 잘못된 것입니다. "리소스"는로드하지 않지만 클래스 경로 대신 파일 시스템에서 직접 파일을로드합니다. jar 파일에서 파일을로드하는 대신 존재하지 않는 파일을 참조하려고하므로 애플리케이션이 어셈블 된 후에는 더 이상 작동하지 않습니다.
— Ben

@ben 귀하의 의견에 감사드립니다. 질문은 kotlin Spek 테스트에서 리소스에서 파일을 읽는 것에 관한 것입니다.
— Krzysztof Ziomek
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.