如何在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
- Gradle:
2. 解决JNA相关类缺失问题
- 确认JNA依赖已正确同步,若依赖未生效,执行构建工具的刷新依赖命令:
- Gradle:
./gradlew build --refresh-dependencies - Maven:
mvn dependency:resolve
- Gradle:
- 确保导入正确的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
相关产品推荐
相关产品推荐

