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

Java如何从System.in逐个读取按键且无需用户按回车提交?

Java中无需回车逐键读取键盘输入的实现方案

核心问题本质

System.in 默认依赖操作系统终端的规范模式(Canonical Mode),这种模式下终端会把输入缓冲到用户按下回车键后才一次性传递给Java程序。所以要实现逐键读取,核心是先修改终端的输入模式为原始模式(Raw Mode),让按键事件直接传递给程序。

实现方案

方案1:通过系统命令临时修改终端模式(需适配不同系统)

针对不同操作系统,我们可以调用系统命令修改终端模式,再读取字节流:

Linux/macOS 示例

import java.io.IOException;
import java.io.InputStream;

public class KeyReader {
    public static void main(String[] args) throws IOException, InterruptedException {
        // 切换终端到原始模式
        new ProcessBuilder("stty", "-icanon", "min", "1").inheritIO().start().waitFor();
        try {
            InputStream in = System.in;
            int c;
            System.out.println("按任意键输入(按q退出):");
            while ((c = in.read()) != -1) {
                char key = (char) c;
                System.out.println("你按下了: " + key);
                if (key == 'q') {
                    break;
                }
            }
        } finally {
            // 恢复终端到规范模式
            new ProcessBuilder("stty", "icanon").inheritIO().start().waitFor();
        }
    }
}

Windows 示例

Windows下需要调用mode con命令修改输入模式:

import java.io.IOException;
import java.io.InputStream;

public class WindowsKeyReader {
    public static void main(String[] args) throws IOException, InterruptedException {
        // 切换终端到即时输入模式
        new ProcessBuilder("cmd.exe", "/c", "mode con: cols=80 lines=25 /n").inheritIO().start().waitFor();
        try {
            InputStream in = System.in;
            int c;
            System.out.println("按任意键输入(按q退出):");
            while ((c = in.read()) != -1) {
                char key = (char) c;
                System.out.println("你按下了: " + key);
                if (key == 'q') {
                    break;
                }
            }
        } finally {
            // 恢复终端模式
            new ProcessBuilder("cmd.exe", "/c", "mode con: cols=80 lines=25 /y").inheritIO().start().waitFor();
        }
    }
}

方案2:使用第三方终端处理库(推荐跨场景)

如果需要更稳定的跨平台支持,推荐使用JLine库,它封装了终端模式的修改逻辑,支持逐键读取、快捷键识别等功能:

  1. 添加Maven依赖(或手动引入对应JAR包):
<dependency>
    <groupId>org.jline</groupId>
    <artifactId>jline</artifactId>
    <version>3.24.1</version>
</dependency>
  1. 示例代码:
import org.jline.reader.LineReader;
import org.jline.reader.LineReaderBuilder;
import org.jline.terminal.Terminal;
import org.jline.terminal.TerminalBuilder;

import java.io.IOException;

public class JLineKeyReader {
    public static void main(String[] args) throws IOException {
        Terminal terminal = TerminalBuilder.terminal();
        LineReader reader = LineReaderBuilder.builder().terminal(terminal).build();
        terminal.enterRawMode();
        try {
            System.out.println("按任意键输入(按q退出):");
            int c;
            while ((c = reader.readCharacter()) != -1) {
                char key = (char) c;
                System.out.println("你按下了: " + key);
                if (key == 'q') {
                    break;
                }
            }
        } finally {
            terminal.close();
        }
    }
}

关于搜索不到解决方案的原因

并非因为Java是GUI导向语言,核心原因是:

  • Java标准库没有直接提供修改终端输入模式的API,这类操作属于操作系统底层交互,需要依赖本地调用或第三方库;
  • 解决方案高度依赖操作系统,没有统一的跨平台原生实现,若搜索时未明确指定平台或精准关键词(如“Java raw terminal input”),不容易找到准确方案;
  • 多数Java控制台程序默认使用行输入,逐键读取的需求相对小众,相关讨论和示例较少。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 19:37:35