1. 概要

このチュートリアルでは、Javaのファイルからを読み取るさまざまな方法について説明します。

最初に、クラスパス、URL、または標準のJavaクラスを使用してJARファイルからファイルをロードする方法を学習します。

次に、 BufferedReader Scanner StreamTokenizer DataInputStream SequenceInputStream、およびFileChannel。 また、UTF-8でエンコードされたファイルの読み取り方法についても説明します。

最後に、Java7およびJava8でファイルをロードおよび読み取るための新しい手法について説明します。

この記事は、Baeldungの「Java –BacktoBasic」シリーズの一部です。

2. 設定

2.1. 入力ファイル

この記事全体のほとんどの例では、ファイル名fileTest.txtのテキストファイルを読み取ります。このファイルには次の1行が含まれています。

Hello, world!

いくつかの例では、別のファイルを使用します。 このような場合、ファイルとその内容について明示的に言及します。

2.2. ヘルパーメソッド

コアJavaクラスのみを使用した一連のテスト例を使用し、テストでは、Hamcrestマッチャーを使用したアサーションを使用します。

テストは共通点を共有します readFromInputStream を変換するメソッド InputStream 結果の主張を容易にするために:

private String readFromInputStream(InputStream inputStream)
  throws IOException {
    StringBuilder resultStringBuilder = new StringBuilder();
    try (BufferedReader br
      = new BufferedReader(new InputStreamReader(inputStream))) {
        String line;
        while ((line = br.readLine()) != null) {
            resultStringBuilder.append(line).append("\n");
        }
    }
  return resultStringBuilder.toString();
}

これと同じ結果を達成する他の方法があることに注意してください。 相談できます この記事 いくつかの選択肢について。

3. クラスパスからのファイルの読み取り

3.1. 標準Javaの使用

このセクションでは、クラスパスで使用可能なファイルを読み取る方法について説明します。 「fileTest.txt」の下で利用可能 src / main / resources:

@Test
public void givenFileNameAsAbsolutePath_whenUsingClasspath_thenFileData() {
    String expectedData = "Hello, world!";
    
    Class clazz = FileOperationsTest.class;
    InputStream inputStream = clazz.getResourceAsStream("/fileTest.txt");
    String data = readFromInputStream(inputStream);

    Assert.assertThat(data, containsString(expectedData));
}

上記のコードスニペットでは、現在のクラスを使用して getResourceAsStream メソッドを使用してファイルをロードし、ロードするファイルの絶対パスを渡しました。

同じ方法が利用可能です ClassLoader インスタンスも:

ClassLoader classLoader = getClass().getClassLoader();
InputStream inputStream = classLoader.getResourceAsStream("fileTest.txt");
String data = readFromInputStream(inputStream);

取得します classLoader 現在のクラスの getClass()。getClassLoader().

主な違いは、 getResourceAsStream ClassLoader たとえば、パスはクラスパスのルートから始まる絶対パスとして扱われます。

に対して使用される場合 クラス 実例, パスは、パッケージからの相対パス、または先頭のスラッシュで示される絶対パスである可能性があります。

もちろん、実際には、この例の InputStream のように、開いているストリームは常に閉じている必要があることに注意してください

InputStream inputStream = null;
try {
    File file = new File(classLoader.getResource("fileTest.txt").getFile());
    inputStream = new FileInputStream(file);
    
    //...
}     
finally {
    if (inputStream != null) {
        try {
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3.2. commons-ioライブラリの使用

もう1つの一般的なオプションは、commons-ioパッケージのFileUtilsクラスを使用することです。

@Test
public void givenFileName_whenUsingFileUtils_thenFileData() {
    String expectedData = "Hello, world!";
        
    ClassLoader classLoader = getClass().getClassLoader();
    File file = new File(classLoader.getResource("fileTest.txt").getFile());
    String data = FileUtils.readFileToString(file, "UTF-8");
        
    assertEquals(expectedData, data.trim());
}

ここでは、 FileオブジェクトをFileUtilsクラスのメソッドreadFileToString()に渡します。 このユーティリティクラスは、 InputStream インスタンスを作成してデータを読み取るためのボイラープレートコードを記述せずに、コンテンツをロードすることができます。

同じライブラリは、 IOUtils クラスも提供します。

@Test
public void givenFileName_whenUsingIOUtils_thenFileData() {
    String expectedData = "Hello, world!";
        
    FileInputStream fis = new FileInputStream("src/test/resources/fileTest.txt");
    String data = IOUtils.toString(fis, "UTF-8");
        
    assertEquals(expectedData, data.trim());
}

ここでは、 FileInputStreamオブジェクトをIOUtilsクラスのメソッドtoString()に渡します。 このユーティリティクラスは、 InputStream インスタンスを作成してデータを読み取るために、前のクラスと同じように機能します。

4. BufferedReaderで読み取る

次に、ファイルのコンテンツを解析するさまざまな方法に焦点を当てましょう。

BufferedReader:を使用してファイルから読み取る簡単な方法から始めます。

@Test
public void whenReadWithBufferedReader_thenCorrect()
  throws IOException {
     String expected_value = "Hello, world!";
     String file ="src/test/resources/fileTest.txt";
     
     BufferedReader reader = new BufferedReader(new FileReader(file));
     String currentLine = reader.readLine();
     reader.close();

    assertEquals(expected_value, currentLine);
}

readLine()は、ファイルの終わりに達するとnullを返すことに注意してください。

5. JavaNIOを使用したファイルからの読み取り

JDK7では、NIOパッケージが大幅に更新されました。

FilesクラスとreadAllLinesメソッドを使用した例を見てみましょう。 The readAllLines メソッドは道。

パスクラスは、 java.io.File のアップグレードと見なすことができ、いくつかの追加操作が実行されます。

5.1. 小さなファイルを読む

次のコードは、新しいFilesクラスを使用して小さなファイルを読み取る方法を示しています。

@Test
public void whenReadSmallFileJava7_thenCorrect()
  throws IOException {
    String expected_value = "Hello, world!";

    Path path = Paths.get("src/test/resources/fileTest.txt");

    String read = Files.readAllLines(path).get(0);
    assertEquals(expected_value, read);
}

バイナリデータが必要な場合は、 readAllBytes()メソッドも使用できることに注意してください。

5.2. 大きなファイルを読む

Files クラスで大きなファイルを読み取りたい場合は、BufferedReader。を使用できます。

次のコードは、新しいFilesクラスとBufferedReaderを使用してファイルを読み取ります。

@Test
public void whenReadLargeFileJava7_thenCorrect()
  throws IOException {
    String expected_value = "Hello, world!";

    Path path = Paths.get("src/test/resources/fileTest.txt");

    BufferedReader reader = Files.newBufferedReader(path);
    String line = reader.readLine();
    assertEquals(expected_value, line);
}

5.3. Files.lines()を使用してファイルを読み取る

JDK8は、 Filesクラス内にlines()メソッドを提供します。 文字列要素のStreamを返します。

データをバイトに読み取り、UTF-8文字セットを使用してデコードする方法の例を見てみましょう。

次のコードは、新しい Files.lines()を使用してファイルを読み取ります。

@Test
public void givenFilePath_whenUsingFilesLines_thenFileData() {
    String expectedData = "Hello, world!";
         
    Path path = Paths.get(getClass().getClassLoader()
      .getResource("fileTest.txt").toURI());
         
    Stream<String> lines = Files.lines(path);
    String data = lines.collect(Collectors.joining("\n"));
    lines.close();
         
    Assert.assertEquals(expectedData, data.trim());
}

ファイル操作のようにIOチャネルでStreamを使用するには、 close()メソッドを使用してストリームを明示的に閉じる必要があります。

ご覧のとおり、 Files APIは、ファイルの内容をStringに読み込む別の簡単な方法を提供します。

次のセクションでは、状況によっては適切な、あまり一般的ではないファイルの読み取り方法について説明します。

6. スキャナーで読む

次に、スキャナーを使用してファイルから読み取ります。 ここでは、区切り文字として空白を使用します。

@Test
public void whenReadWithScanner_thenCorrect()
  throws IOException {
    String file = "src/test/resources/fileTest.txt";
    Scanner scanner = new Scanner(new File(file));
    scanner.useDelimiter(" ");

    assertTrue(scanner.hasNext());
    assertEquals("Hello,", scanner.next());
    assertEquals("world!", scanner.next());

    scanner.close();
}

デフォルトの区切り文字は空白ですが、スキャナーでは複数の区切り文字を使用できることに注意してください。

Scannerクラスは、コンソールからコンテンツを読み取る場合、またはコンテンツに既知の区切り文字(スペースで区切られた整数のリスト)を含むプリミティブ値が含まれている場合に役立ちます。

7. StreamTokenizerで読み取る

次に、StreamTokenizerを使用してテキストファイルをトークンに読み込みます。

トークナイザーは、最初に次のトークンが何であるか、文字列または数値を把握することによって機能します。 これを行うには、tokenizer.ttypeフィールドを確認します。

次に、このタイプに基づいて実際のトークンを読み取ります。

  • tokenizer.nval –タイプが数値の場合
  • tokenizer.sval –タイプが文字列の場合

この例では、以下を含む別の入力ファイルを使用します。

Hello 1

次のコードは、ファイルから文字列と数値の両方を読み取ります。

@Test
public void whenReadWithStreamTokenizer_thenCorrectTokens()
  throws IOException {
    String file = "src/test/resources/fileTestTokenizer.txt";
   FileReader reader = new FileReader(file);
    StreamTokenizer tokenizer = new StreamTokenizer(reader);

    // token 1
    tokenizer.nextToken();
    assertEquals(StreamTokenizer.TT_WORD, tokenizer.ttype);
    assertEquals("Hello", tokenizer.sval);

    // token 2    
    tokenizer.nextToken();
    assertEquals(StreamTokenizer.TT_NUMBER, tokenizer.ttype);
    assertEquals(1, tokenizer.nval, 0.0000001);

    // token 3
    tokenizer.nextToken();
    assertEquals(StreamTokenizer.TT_EOF, tokenizer.ttype);
    reader.close();
}

最後にファイルの終わりトークンがどのように使用されているかに注意してください。

このアプローチは、入力ストリームをトークンに解析するのに役立ちます。

8. DataInputStreamで読み取る

DataInputStream を使用して、ファイルからバイナリまたはプリミティブデータ型を読み取ることができます。

次のテストでは、DataInputStreamを使用してファイルを読み取ります。

@Test
public void whenReadWithDataInputStream_thenCorrect() throws IOException {
    String expectedValue = "Hello, world!";
    String file ="src/test/resources/fileTest.txt";
    String result = null;

    DataInputStream reader = new DataInputStream(new FileInputStream(file));
    int nBytesToRead = reader.available();
    if(nBytesToRead > 0) {
        byte[] bytes = new byte[nBytesToRead];
        reader.read(bytes);
        result = new String(bytes);
    }

    assertEquals(expectedValue, result);
}

9. FileChannelで読み取る

大きなファイルを読み取る場合、FileChannelは標準IOよりも高速になる可能性があります。

次のコードは、FileChannelおよびRandomAccessFileを使用してファイルからデータバイトを読み取ります。

@Test
public void whenReadWithFileChannel_thenCorrect()
  throws IOException {
    String expected_value = "Hello, world!";
    String file = "src/test/resources/fileTest.txt";
    RandomAccessFile reader = new RandomAccessFile(file, "r");
    FileChannel channel = reader.getChannel();

    int bufferSize = 1024;
    if (bufferSize > channel.size()) {
        bufferSize = (int) channel.size();
    }
    ByteBuffer buff = ByteBuffer.allocate(bufferSize);
    channel.read(buff);
    buff.flip();
    
    assertEquals(expected_value, new String(buff.array()));
    channel.close();
    reader.close();
}

10. UTF-8エンコードファイルの読み取り

次に、を使用してUTF-8でエンコードされたファイルを読み取る方法を見てみましょう。 BufferedReader。 この例では、漢字を含むファイルを読み取ります。

@Test
public void whenReadUTFEncodedFile_thenCorrect()
  throws IOException {
    String expected_value = "青空";
    String file = "src/test/resources/fileTestUtf8.txt";
    BufferedReader reader = new BufferedReader
      (new InputStreamReader(new FileInputStream(file), "UTF-8"));
    String currentLine = reader.readLine();
    reader.close();

    assertEquals(expected_value, currentLine);
}

11. URLからコンテンツを読み取る

URLからコンテンツを読み取るには、この例では「/」URLを使用します。

@Test
public void givenURLName_whenUsingURL_thenFileData() {
    String expectedData = "Baeldung";

    URL urlObject = new URL("/");
    URLConnection urlConnection = urlObject.openConnection();
    InputStream inputStream = urlConnection.getInputStream();
    String data = readFromInputStream(inputStream);

    Assert.assertThat(data, containsString(expectedData));
}

URLに接続する別の方法もあります。 ここでは、 URLURLConnection 標準SDKで利用可能なクラス。

12. JARからのファイルの読み取り

JARファイル内にあるファイルを読み取るには、ファイルが含まれているJARが必要です。 この例では、「hamcrest-library-1.3.jar」ファイルから「LICENSE.txt」を読み取ります。

@Test
public void givenFileName_whenUsingJarFile_thenFileData() {
    String expectedData = "BSD License";

    Class clazz = Matchers.class;
    InputStream inputStream = clazz.getResourceAsStream("/LICENSE.txt");
    String data = readFromInputStream(inputStream);

    Assert.assertThat(data, containsString(expectedData));
}

ここでは、Hamcrestライブラリにある LICENSE.txt をロードするため、リソースの取得に役立つMatcherのクラスを使用します。 クラスローダーを使用して同じファイルをロードすることもできます。

13. 結論

ご覧のとおり、プレーンJavaを使用してファイルをロードし、そこからデータを読み取るには、多くの可能性があります。

クラスパス、URL、jarファイルなどのさまざまな場所からファイルをロードできます。

次に、 BufferedReader を使用して行ごとに読み取り、 Scanner を使用してさまざまな区切り文字を使用して読み取り、StreamTokenizerを使用してファイルをトークンに読み取ります。DataInputStream[X187X ]バイナリデータとプリミティブデータ型を読み取る場合、 SequenceInput Stream を使用して複数のファイルを1つのストリームにリンクする場合、FileChannelを使用して大きなファイルからより高速に読み取る場合など。

この記事のソースコードは次の場所にあります。 GitHubリポジトリ.