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();
}

次の例のように、

findWithinHorizo​​n()

を使用して特定のドメイン内の

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ベースのプロジェクトなので、インポートは簡単ですそのまま実行します。