Kotlin and Gradle - Reading from stdio

偶尔善良 提交于 2019-12-30 09:36:45

问题


I am trying to execute my Kotlin class using the command:

./gradlew -q run < src/main/kotlin/samples/input.txt

Here is my HelloWorld.kt class:

package samples

fun main(args: Array<String>) {

    println("Hello, world!")

    val lineRead = readLine()
    println(lineRead)
}

Here is my build.gradle.kts:

plugins {
    kotlin("jvm")
    application
}

application {
    mainClassName = "samples.HelloWorldKt"
}

dependencies {
    compile(kotlin("stdlib"))
}

repositories {
    jcenter()
}

The code executes, but the data contained inside the input.txt file is not displayed. Here is the output I get:

Hello, world!
null

I want to be able to execute the gradlew command above and the input.txt stream be redirected to stdio. I can easily do that in C++. Once I compile my .cpp file, I can run:

./my_code < input.txt

and it executes as expected.

How can I achieve the same thing with Kotlin and Gradle?

Update: Based on this answer, I've tried adding this to build.gradle.kts but it is not a valid syntax:


回答1:


AjahnCharles suggestion about run { standardInput = System.in } is correct, but to port it to kotlin-dsl you need a different syntax. run in this case is the task name and you configure existing task of application plugin. To configure existing task in kotlin-dsl you should use one of this ways:

val run by tasks.getting(JavaExec::class) {
    standardInput = System.`in`
}

or

val run: JavaExec by tasks
run.standardInput = System.`in`

The upcoming version of Gradle 4.3 should provide API for plugin writers to read user input.

The reason of difference between of Groovy and Kotlin in this case because Groovy uses dynamic types, but in Kotlin you must specify task type to have autocompletion and just to compile config script




回答2:


Almost, but this doesn't work :'(

In Theory

My understanding: < input.txt sets the standard input for the gradlew process, but by default this is not forwarded to your program.

You want to add this to your build.gradle.kts:

run {
    standardInput = System.`in`
}

Sources:
https://discuss.gradle.org/t/why-doesnt-system-in-read-block-when-im-using-gradle/3308/2
https://discuss.gradle.org/t/how-can-i-execute-a-java-application-that-asks-for-user-input/3264


In Practice

These build configs look about the same to me, yet Groovy works and Kotlin doesn't. I'm starting to think that the Gradle Kotlin DSL doesn't support the standardInput term yet :/

Here's my working Groovy version if that's any help:

apply plugin: 'kotlin'
apply plugin: 'application'

buildscript {
    ext.kotlin_version = '1.1.4'

    repositories {
        jcenter()
    }

    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

repositories {
    jcenter()
}

dependencies {
    // api => exported to consumers (found on their compile classpath)
    // implementation => used internally (not exposed to consumers)
    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}

mainClassName = "samples.HelloWorldKt"

run {
    standardInput = System.in
}


来源:https://stackoverflow.com/questions/45747112/kotlin-and-gradle-reading-from-stdio

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!