torutkのブログ

ソフトウェア・エンジニアのブログ

Java SE 7の新しいファイルI/O

今まで、なかなかJava SE 7の新しいAPIに取り組めていなかったので、ちょっとしたツールを作成する機会に、コマンドライン引数で指定したファイルを読み込むという、よくありがちなシナリオで、Java SE 7の新しいファイルI/OのAPIを試してみました。

新しいAPIの解説記事はいろいろ出ていますが、意外とわかりづらかったので(解説指向で高度な内容を書かれているためと思われる)、ごく簡単なシナリオでどんなコードになるかをみてみました。

import java.io.BufferedReader;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

これがテキストファイル読み込みで必要な役者一揃いです。ファイルの読み込み自体は従来からおなじみのBufferedReaderです。チェック例外のIOExceptionも十分なじみのクラスです。
文字コードを指定するのに、Charsetが必要になります。
コマンドライン引数で指定するファイルのパス文字列からBufferedReaderを生成するまでの役者が、Files、Path、Pathsの3人です。

public class ReadSample {
    public static void main(String[] args) {
        Path path = Paths.get(args[0]);

エラー処理はとっぱらって、とりあえずコマンドラインで指定するであろうパス文字列(相対パスだったり絶対パスだったりは使う人によって異なります)を、PathsクラスのstaticメソッドgetでPathオブジェクトにしています*1

        if (!Files.isReadable(path)) {
            // 読み込み不可・・・
         }

ファイルのアクセス可否を調べるメソッドがFilesクラスに用意されています。例えば、exists, isReadable, isWritable, isExecutalbe, isDirectory, isSymbolicLink などのメソッドがあります。

        try (BufferedReader r = Files.newBufferedReader(path, Charset.forName("UTF-8"))) {
            String line = r.readLine();
            while (line != null) {
                // 読み込み処理
            }
        } catch (IOException e) {
            // エラー処理
        }

テキストファイルの読み込みの場合、FilesクラスのstaticメソッドnewBufferedReaderで一気にBufferedReaderオブジェクトを作成します。従来の方法だと、FileInputStreamを作ってInputStreamReaderを作ってやっとBufferedReaderを作るという3段階が必要でした*2

また、ファイルをオープンしたときには必ずクローズが必要ですが、Java SE 7の新しいtry文の文法で自動的にクローズするように記述しました。



*1:ここで、「Paths.getは実はFileSystems.getDefault().getPath()」のことだなどというと混乱するので、聞かなかったことにします。

*2:エンコーディングを明示的に指定する場合。エンコーディングがデフォルトでよい場合(コーディングとしては非推奨)は、FileRearderを作ってBufferedReaderを作る2段階。