標準入力から読み取る(Java)
Javaで簡単なアプリを作ってたんだけど、標準入力から文字なり数値なりを受け取るやり方を忘れてたので、メモしておく。
Scanfを使って書いたのが、これ。
Test.jva
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
int num = inputNum();
String txt = inputTxt();
System.out.println("num:" + num + " txt:" + txt);
}
public static int inputNum() {
Scanner scanner = new Scanner(System.in);
System.out.print("num > ");
int num = scanner.nextInt();
scanner.nextLine(); // 数字入力のあとの改行コードを吸い取る
scanner.close();
return num;
}
public static String inputTxt() {
Scanner scanner = new Scanner(System.in);
System.out.print("txt > ");
String txt = scanner.nextLine();
scanner.close();
return txt;
}
}
これを実行すると、以下のようになる。
$ java Test
num > 23
txt > Exception in thread "main" java.util.NoSuchElementException: No line found
at java.base/java.util.Scanner.nextLine(Scanner.java:1651)
at Test.inputTxt(Unknown Source)
at Test.main(Unknown Source)
で、標準入力は1つしかないんだし、2つインスタンスを作成して、JVMも困ってしまったんだろうな。
作り直したのが、これ。
Test2.java
import java.util.Scanner;
public class Test2 {
static Scanner scanner = null;
public static void main(String[] args) {
int num = inputNum();
String txt = inputTxt();
System.out.println("num:" + num + " txt:" + txt);
scanner.close();
}
public static int inputNum() {
scanner = new Scanner(System.in);
System.out.print("num > ");
int num = scanner.nextInt();
scanner.nextLine(); // 数字入力のあとの改行コードを吸い取る
return num;
}
public static String inputTxt() {
scanner = new Scanner(System.in);
System.out.print("txt > ");
String txt = scanner.nextLine();
return txt;
}
}
実行結果
$ java Test2
num > 23
txt > あめま
num:23 txt:あめま
BufferedReader – InputStreamReader の場合
もうひとつの場合はどうなんだろう?
Test3.java
import java.util.Scanner;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.IOException;
public class Test3 {
public static void main(String[] args) {
int num = inputNum();
String txt = inputTxt();
System.out.println("num:" + num + " txt:" + txt);
}
public static int inputNum() {
InputStreamReader is = new InputStreamReader(System.in);
BufferedReader stdin = new BufferedReader(is);
System.out.print("num > ");
int num = 0;
try {
String txtNum = stdin.readLine();
num = Integer.parseInt(txtNum);
} catch (IOException e) {
e.printStackTrace();
}
return num;
}
public static String inputTxt() {
InputStreamReader is = new InputStreamReader(System.in);
BufferedReader stdin = new BufferedReader(is);
String txt = null;
System.out.print("txt > ");
try {
txt = stdin.readLine();
} catch (IOException e) {
e.printStackTrace();
}
return txt;
}
}
実行例
$ java Test3
num > 34
txt > かい〜の
num:34 txt:かい〜の
これはうまくいくのである。
ただ、close処理を付け加えるとうまくいかなくなる。
Test4.java
import java.util.Scanner;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.IOException;
public class Test4 {
public static void main(String[] args) {
int num = inputNum();
String txt = inputTxt();
System.out.println("num:" + num + " txt:" + txt);
}
public static int inputNum() {
InputStreamReader is1 = new InputStreamReader(System.in);
BufferedReader stdin1 = new BufferedReader(is1);
System.out.print("num > ");
int num = 0;
try {
String txtNum = stdin1.readLine();
num = Integer.parseInt(txtNum);
} catch (IOException e) {
e.printStackTrace();
} finally {
// クローズ処理
if (stdin1 != null) {
try {
stdin1.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return num;
}
public static String inputTxt() {
InputStreamReader is2 = new InputStreamReader(System.in);
BufferedReader stdin2 = new BufferedReader(is2);
String txt = null;
System.out.print("txt > ");
try {
txt = stdin2.readLine();
} catch (IOException e) {
e.printStackTrace();
} finally {
// クローズ処理
if (stdin2 != null) {
try {
stdin2.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return txt;
}
}
実行例
$ java Test4
num > 56
txt > java.io.IOException: Stream closed
at java.base/java.io.BufferedInputStream.getBufIfOpen(BufferedInputStream.java:176)
at java.base/java.io.BufferedInputStream.read(BufferedInputStream.java:342)
at java.base/sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
at java.base/sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
at java.base/sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
at java.base/java.io.InputStreamReader.read(InputStreamReader.java:181)
at java.base/java.io.BufferedReader.fill(BufferedReader.java:161)
at java.base/java.io.BufferedReader.readLine(BufferedReader.java:326)
at java.base/java.io.BufferedReader.readLine(BufferedReader.java:392)
at Test4.inputTxt(Unknown Source)
at Test4.main(Unknown Source)
num:56 txt:null
やはり、標準入力は一つなんだし、たとえインスタンスに別々の名前をつけていても、 ひとつをクローズしてしまえば、そのストリームは使えなくなるみたい。
Scanner と同じで、ストリームを開いてインスタンスを作ったら、それに対して いろいろとアクセスしなければならない。
で、最後に close処理をすることになるのかな。
カテゴリー: Java, memo
タグ: BufferedReader, java, Scanner, stdin, 標準入力
カウント: 204