Javaスキャナー
1概要
このチュートリアルでは、
Java
Scanner
を使用して入力を読み取り、さまざまな区切り文字を持つパターンを見つけてスキップする方法を説明します。
2ファイルをスキャンする
まず、
Scanner
を使用してファイルを読み取る方法を見てみましょう。次の例では、
Scanner
を使用して「
Hello world
」を含むファイルをトークンに読み込みます。
@Test
public void whenReadFileWithScanner__thenCorrect() throws IOException{
Scanner scanner = new Scanner(new File("test.txt"));
assertTrue(scanner.hasNext());
assertEquals("Hello", scanner.next());
assertEquals("world", scanner.next());
scanner.close();
}
注:
Scanner
メソッド
next()
は、次の
String
トークンを返します。
3
InputStream
を
String
に変換
次に、
Scanner
を使用して
InputStream
を
String
に変換する方法を見てみましょう。
@Test
public void whenConvertInputStreamToString__thenConverted() throws IOException {
String expectedValue = "Hello world";
FileInputStream inputStream = new FileInputStream("test.txt");
Scanner scanner = new Scanner(inputStream);
scanner.useDelimiter("A");
String result = scanner.next();
assertEquals(expectedValue, result);
scanner.close();
}
注:前の例では、
Scanner
をトリックして、ストリーム全体を先頭から次の正規表現「A」(入力の先頭に一致)までトークン化しました。
4
Scanner
と
BufferedReader
それでは、
Scanner
と
BufferedReader
の違いについて説明しましょう。
-
BufferedReader
入力を行に読みたいとき**
入力を
トークンに読み込む
Scanner
次の例では、
BufferedReader
を使用してファイルを行単位で読み込んでいます。
@Test
public void whenReadUsingBufferedReader__thenCorrect() throws IOException {
String firstLine = "Hello world";
String secondLine = "Hi, John";
BufferedReader reader = new BufferedReader(new FileReader("test.txt"));
String result = reader.readLine();
assertEquals(firstLine, result);
result = reader.readLine();
assertEquals(secondLine, result);
reader.close();
}
それでは、同じファイルをトークンに読み込むために
Scanner
を使用しましょう。
@Test
public void whenReadUsingScanner__thenCorrect() throws IOException {
String firstLine = "Hello world";
FileInputStream inputStream = new FileInputStream("test.txt");
Scanner scanner = new Scanner(inputStream);
String result = scanner.nextLine();
assertEquals(firstLine, result);
scanner.useDelimiter(", ");
assertEquals("Hi", scanner.next());
assertEquals("John", scanner.next());
scanner.close();
}
注:
Scanner
nextLine()
APIを使用して行全体を読み取ることもできます。
5
new Scanner(System.in)を使用したコンソールからのスキャン入力
次に、
Scanner
を使用してコンソールから入力を読み取る方法を見てみましょう。
@Test
public void whenReadingInputFromConsole__thenCorrect() {
String input = "Hello";
InputStream stdin = System.in;
System.setIn(new ByteArrayInputStream(input.getBytes()));
Scanner scanner = new Scanner(System.in);
String result = scanner.next();
assertEquals(input, result);
System.setIn(stdin);
scanner.close();
}
コンソールからの入力をシミュレートするために
System.setIn(…)
を使用したことに注意してください。
5.1.
nextLine()
API
このメソッドは単に現在行の文字列を返します。
scanner.nextLine();
これは現在の行の内容を読み取り、最後の行区切り文字(この場合は改行文字)を除いてそれを返します。
内容を読んだ後、
Scanner
はその位置を次の行の先頭に設定します。覚えておくべき重要な点は、**
__ nextLine()
APIが行区切り文字を消費し、
Scanner__の位置を次の行に移動することです。
そのため、次回は__Scannerを介して読む場合は、次の行の先頭から読みます。
5.2.
nextInt()
API
このメソッドは、入力の次のトークンを
int:
としてスキャンします。
scanner.nextInt();
APIは次に利用可能な整数トークンを読み取ります。この場合、次のトークンが整数でその整数の後に行区切り記号がある場合は、必ず
__ nextInt()
__が行区切り記号を消費しないことを忘れないでください。代わりに、スキャナの位置は行区切り文字そのものになります
。
そのため、最初の操作が
scanner.nextInt()
、次に
scanner.nextLine()
で、一連の操作がある場合は、整数を指定して改行を押すと入力として、両方の操作が実行されます。
nextInt()
APIは整数を消費し、
nextLine()
APIは行区切り文字を消費し、
Scanner
を次の行の先頭に配置します。
6. 入力を検証
それでは、
Scanner
を使用して入力を検証する方法を見てみましょう。次の例では、
Scanner
メソッド
hasNextInt()
を使用して、入力が整数値かどうかを確認します。
@Test
public void whenValidateInputUsingScanner__thenValidated() throws IOException {
String input = "2000";
InputStream stdin = System.in;
System.setIn(new ByteArrayInputStream(input.getBytes()));
Scanner scanner = new Scanner(System.in);
boolean isIntInput = scanner.hasNextInt();
assertTrue(isIntInput);
System.setIn(stdin);
scanner.close();
}
7.
String
をスキャン
次に、
Scanner
を使用して
String
をスキャンする方法を見てみましょう。
@Test
public void whenScanString__thenCorrect() throws IOException {
String input = "Hello 1 F 3.5";
Scanner scanner = new Scanner(input);
assertEquals("Hello", scanner.next());
assertEquals(1, scanner.nextInt());
assertEquals(15, scanner.nextInt(16));
assertEquals(3.5, scanner.nextDouble(), 0.00000001);
scanner.close();
}
注:メソッド
nextInt(16)
は、次のトークンを16進整数値として読み取ります。
8
Pattern
を探す
それでは、
Scanner
を使用して
Pattern
を見つける方法を見てみましょう。
次の例では、
findInLine()
を使用して、入力全体で指定された
Pattern
に一致するトークンを
検索します。
@Test
public void whenFindPatternUsingScanner__thenFound() throws IOException {
String expectedValue = "world";
FileInputStream inputStream = new FileInputStream("test.txt");
Scanner scanner = new Scanner(inputStream);
String result = scanner.findInLine("wo..d");
assertEquals(expectedValue, result);
scanner.close();
}
次の例のように、
findWithinHorizon()
を使用して特定のドメイン内の
Pattern
を検索することもできます。
@Test
public void whenFindPatternInHorizon__thenFound() throws IOException {
String expectedValue = "world";
FileInputStream inputStream = new FileInputStream("test.txt");
Scanner scanner = new Scanner(inputStream);
String result = scanner.findWithinHorizon("wo..d", 5);
assertNull(result);
result = scanner.findWithinHorizon("wo..d", 100);
assertEquals(expectedValue, result);
scanner.close();
}
検索範囲は、検索が実行される単なる文字数です。
9スキップ
パターン
次に、
Scanner
で
Pattern
をスキップする方法を見てみましょう。
Scanner
を使用して入力を読み取るときに、特定のパターンに一致するトークンをスキップできます。
次の例では、
Scanner
メソッド
skip()
を使用して「
Hello
」トークンをスキップします。
@Test
public void whenSkipPatternUsingScanner__thenSkipped() throws IOException {
FileInputStream inputStream = new FileInputStream("test.txt");
Scanner scanner = new Scanner(inputStream);
scanner.skip(".e.lo");
assertEquals("world", scanner.next());
scanner.close();
}
10
Scanner
区切り文字を変更
最後に、
Scanner
区切り文字を変更する方法を見てみましょう。次の例では、デフォルトの
Scanner
デリミタを“
o
”に変更します。
@Test
public void whenChangeScannerDelimiter__thenChanged() throws IOException {
String expectedValue = "Hello world";
String[]splited = expectedValue.split("o");
FileInputStream inputStream = new FileInputStream("test.txt");
Scanner scanner = new Scanner(inputStream);
scanner.useDelimiter("o");
assertEquals(splited[0], scanner.next());
assertEquals(splited[1], scanner.next());
assertEquals(splited[2], scanner.next());
scanner.close();
}
複数の区切り文字を使用することもできます。次の例では、ファイルをスキャンするための区切り文字として、カンマ“
、
”とダッシュ“
–
”の両方を使用しています。“
John、Adam-Tom
”
@Test
public void whenReadWithScannerTwoDelimiters__thenCorrect()
throws IOException {
Scanner scanner = new Scanner(new File("test.txt"));
scanner.useDelimiter(",|-");
assertEquals("John", scanner.next());
assertEquals("Adam", scanner.next());
assertEquals("Tom", scanner.next());
scanner.close();
}
注:
デフォルトの
Scanner
区切り文字
は空白です。
11結論
このチュートリアルでは、
Java Scanner
を使った実際の例をいくつか調べました。
Scanner
を使用して、ファイル、コンソール、または
String
から入力を読み取る方法を学びました。
Scanner
を使用してパターンを見つけてスキップする方法、および
Scanner
区切り文字を変更する方法も学習しました。
これらの例の実装はhttps://github.com/eugenp/tutorials/tree/master/core-java-io[GitHubで公開]にあります – これはMavenベースのプロジェクトなので、インポートは簡単ですそのまま実行します。