親バカエンジニアのナレッジ帳

webのエンジニアをやっており、日頃の開発で詰まったことや書き残しておきたいことを載せています。

Javaのファイル読み込みメソッドを整理

ファイルを読み込む処理

例えばcsvファイルなど、ファイルの内容を読み込んで処理をすることがありますよね。

そんな時にFileInputStreamやらInputStreamReaderやらBufferedReaderを使う必要があるのですが、初見だと何がなにやらさっぱりですよね。

そんなメソッド達の役割を今回は整理してみようと思います。
それぞれの役割を理解すると一連の処理がだいぶ読みやすくなるでしょう。

また、旧来の読み込み方と違い、Java7からはFiles.newBufferedReaderというメソッドも出てきています。
そのあたりも説明していきたいと思います。

※今回は例としてファイルパスは「/example/test.csv」とし、このファイルをUTF-8の文字コードで読み込んでから処理をするものとします。

FileInputStreamでファイルの内容を読み込み

まずは

FileInputStream('/example/test.csv');

でファイルの内容を読み込みましょう。
この時、ファイルはバイトストリームで読み込まれるために、読み込まれた結果を見ても意味のわからない文字の羅列でしかありません。
バイトではなく、文字コードを指定して読み込みたい時に使うのがInputStreamReaderです。

InputStreamReaderで指定した文字コードに

FileInputStreamで読み込んだ次は、

InputStreamReader(FileInputStream('/example/test.csv'), 'utf-8')

のようにInputStreamReaderで囲い、指定した文字コードで読めるようにします。

今回は文字コードでutf-8を指定していますが、文字コードを省略した場合はプラットフォームに依存したデフォルト(省略時)の文字コードが使われます。

ここまで来れば、read()を使って文字を読み出すことができます。

FileReaderを使えばInputStreamReader要らず

FileInputStreamを使う場合はInputStreamReaderで文字コードを変換する必要がありますが、FileReaderを使ってファイルを読み込めば一発でread()が使えるところまで処理を進めることができます。
ただしFileReaderでは文字コードを指定することができません。

一旦ここまでの内容を整理しましょう。

旧来のファイルの読み込み方比較

方法1

InputStreamReader(FileInputStream(ファイルパス), 文字コード);

バイトで読み込んだものを指定した文字コードで読み込みます。
文字コードを省略した場合はプラットフォームに依存したデフォルト(省略時の)文字コードが使われます。

方法2

FileReader(ファイルパス);

InputStreamReaderを使わなくても1発でできます。
文字コードの指定はできません。

どちらの方法でも、このままread()メソッドを使用すれば読み込むことができますが、ループ処理の中で1文字ずつしか取り出せません。

BufferedReaderを使えば一行単位で呼び出し可能に

旧来の書き方の話がまだ続きますが、InputStreamReaderやFileReaderで読み込んだ場合、read()メソッドを使うために1文字ずつしか取り出せないという非効率な側面があります。
それに対してFileReaderを拡張したBufferedReaderを使用すればreadLine()によって一行ずつ取り出すことができるのです。

やりたい内容によって使い分ける必要がありますが、文字数が多いファイルであれば、メモリの関係からもreadLine()を使用することをおすすめします。

Java7からはFiles.newBufferedReaderを利用可能に

Java7からは標準ライブラリとしてjava.nio.file.Filesを使えるようになったため、BufferedReaderを使いたい時は以下の書き方でOKです。

BufferedReader br = Files.newBufferedReader(path, StandardCharsets.UTF_8);

文字コードは省略可能です。
さらにJava8からラムダを使用できるようになったため、Files.linesメソッドを使用すればStreamを使って一行ずつ処理をすることが可能です。
Java8以降でファイルの中身を読み込む時は基本Files.newBufferedReaderを使用すれば問題ないと思います。

まとめ

今回はざっくりメソッドの説明に終始したため、具体的な書き方は載せていません。
どれも調べれば出てくる内容なので、上記の説明を見ながら、処理内容に合った書き方をしてくれればと思います。
何も考えずにread()を使いまくると、残念なことが多いので注意してくださいね。