概要
このエントリでは、Javaでコンソール入出力で動作するプログラムを書くときに、1文字ずつ入力をハンドリングしたい場合の方法について扱います。
背景
Javaでは、標準入出力を扱うStreamがありますが、1文字ずつ入力を「読み込む」ことはできますが、キー入力のイベントを直接ハンドルすることはできません。
このため、例えば「電卓」プログラムを作るときに「+」を押したらすぐに何かの処理を行う、といったことは標準のライブラリだけでは実現できません。
JLineを使う
JLineとは
JLine3は、CUIアプリケーションを開発するときに使えるライブラリです。いくつかの有名どころのOSSでも利用されています。
JLine3は、Windows環境などでのプラットフォーム独自のターミナルの制御にも対応します。ここではプラットフォームネイティブのライブラリが必要となるため、JNAもしくはJANSIを使用する方式が提供されています。このエントリでは、JNAを使用しています。
コードサンプル
下記のコードを使うと、1文字ずつターミナルから入力し、即時に標準出力に表示しています。
package com.hrkt.commandlinecalculator;
import lombok.extern.slf4j.Slf4j;
import org.jline.terminal.Terminal;
import org.jline.terminal.TerminalBuilder;
import org.springframework.stereotype.Component;
import java.io.IOException;
@Component
@Slf4j
public class CommandlineInterface {
public void run(String... args) {
log.info("hello");
try(Terminal terminal = TerminalBuilder.terminal()) {
int ch = 0;
while ((ch = terminal.reader().read()) != 0x09){
// TAB(0x09)で抜ける
char c = (char)ch;
System.out.println(String.format("%d, %c", ch, ch));
}
} catch(IOException e) {
log.error(e.getMessage(), e);
}
}
}
下図のような動きとなります。
おわりに
このエントリでは、Javaでコンソールからのキー入力をハンドルする方法について紹介しました。
JLine2を利用した記事も見かけますが、開発が終わっているものであり、JLine3を使うことが推奨されています。
コードのサンプル
動作するサンプルは、下記に置いてあります。