You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Kotlin JVM/原生环境下直接读取键盘输入(非readln())

Kotlin JVM控制台无readln()的键盘输入实现及问题解决

问题背景

我需要一种无需使用readln()即可在Kotlin中直接读取键盘输入的方法。曾在Kotlin文档中找到org.w3c.dom.events.KeyboardEvent相关内容,但该方法仅适用于JavaScript环境,而我使用的是JVM/原生环境。补充说明:我的应用是纯控制台程序。

尝试过程及问题

更新1:RawConsoleInput类找不到异常

尝试了lukas.j提供的RawConsoleInput方案,当read()方法参数缺失时,提示“no value passed for read()”,说明能找到该类;但参数正确后,出现如下异常:

Exception in thread "main" java.lang.NoClassDefFoundError: RawConsoleInput
        at MainKt.main(Main.kt:5)
        at MainKt.main(Main.kt)
Caused by: java.lang.ClassNotFoundException: RawConsoleInput
        at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
        at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:525)
        ... 2 more

更新2:JNA依赖引入后的类型及类缺失问题

已添加该类并转换为Kotlin,同时引入JNA依赖implementation("net.java.dev.jna:jna:5.14.0"),但现在出现大量类缺失问题:Native.load、LastErrorException,还存在错误提示“Operator '=' cannot be applied to 'Long' and 'Int'”(翻译:操作符'='不能应用于'Long'和'Int'类型)

解决方案

1. 修复ClassNotFoundException问题

  • 确认RawConsoleInput类的文件路径与包声明完全匹配,且放置在项目的源码目录下(如src/main/kotlin),确保编译时能被正确扫描到。
  • 若使用构建工具(Gradle/Maven),执行清理构建命令刷新classpath:
    • Gradle:./gradlew clean build
    • Maven:mvn clean install

2. 解决JNA相关类缺失问题

  • 确认JNA依赖已正确同步,若依赖未生效,执行构建工具的刷新依赖命令:
    • Gradle:./gradlew build --refresh-dependencies
    • Maven:mvn dependency:resolve
  • 确保导入正确的JNA包,避免类引用错误:
    import com.sun.jna.Native
    import com.sun.jna.LastErrorException
    import com.sun.jna.platform.win32.Kernel32
    import com.sun.jna.platform.win32.WinNT
    

3. 修复类型不匹配问题

Kotlin中===用于判断对象引用是否相等,且要求左右两侧类型完全一致。针对Long与Int的比较错误,需将其中一方转换为匹配类型:

// 错误示例
if (longValue === intValue) { /* ... */ }

// 正确写法1:将Int转为Long(推荐,避免溢出)
if (longValue == intValue.toLong()) { /* ... */ }

// 正确写法2:将Long转为Int(需注意数值溢出风险)
if (longValue.toInt() === intValue) { /* ... */ }

替代方案:Java原生API实现无缓冲输入

若JNA方案过于繁琐,可使用Java原生API实现无回显、实时的键盘输入(跨Windows/Linux):

import java.io.BufferedReader
import java.io.InputStreamReader
import java.util.concurrent.Executors
import kotlin.system.exitProcess

fun main() {
    val executor = Executors.newSingleThreadExecutor()
    executor.submit {
        val reader = BufferedReader(InputStreamReader(System.`in`))
        while (true) {
            val inputCode = reader.read()
            if (inputCode == -1) break
            val keyChar = inputCode.toChar()
            println("按下按键:$keyChar(ASCII码:$inputCode)")
            // 按ESC键退出程序
            if (inputCode == 27) exitProcess(0)
        }
    }
    println("按下任意键(ESC退出)...")
    executor.awaitTermination(Long.MAX_VALUE, java.util.concurrent.TimeUnit.NANOSECONDS)
}

内容的提问来源于stack exchange,提问作者ValleyDragon888

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 16:26:09