このページを正しく表示するには、ブラウザでJavaScriptを有効にする必要があります。
コース: 重要なクラス
レッスン: 基本的なI/O
セクション: ファイルI/O(NIO.2を含む)
ファイルの読取り、書込み、作成
ホームページ > 重要なクラス > 基本的なI/O

ファイルの読取り、書込み、作成

このページでは、ファイルの読取り、書込み、作成、オープンの詳細について説明します。 多様なファイルI/Oメソッドを使用できます。 APIを理解しやすいように、次の図ではファイルI/Oメソッドを左から順に単純なものから複雑なものとなるように並べています。

Line drawing with file I/O methods arranged from least complex (on the left) to most complex (on the right).

単純なものから複雑なものへと並べたファイルI/Oメソッド

図の左端に位置するのは、ユーティリティ・メソッドであるreadAllBytesreadAllLineswriteです。これらは一般的なケースで使用するために設計された単純なメソッドです。 その右には、newBufferedReadernewBufferedWriter、さらにnewInputStreamnewOutputStreamなど、ストリームやテキスト行の反復処理に使用するメソッドが続きます。 これらのメソッドは、java.ioパッケージとの相互運用性があります。 さらにその右には、newByteChannelメソッドなどの、ByteChannelSeekableByteChannelByteBufferを扱うメソッドがあります。 最後に、右端には、FileChannelを使用するメソッドが位置します。これらのメソッドは、ファイルのロックやメモリマップI/Oなどを必要とする高度なアプリケーションで使用します。


注:新規のファイルを作成するメソッドでは、ファイルの初期属性セットをオプションで指定できます。 たとえば、POSIX標準セットをサポートするファイル・システム(UNIXなど)では、ファイル作成時にファイル所有者、グループ所有者、ファイル権限を指定できます。 『メタデータの管理』のページで、ファイル属性と、そのアクセス方法や設定方法について説明しています。

このページでは次のトピックについて説明します。


OpenOptionパラメータ

このセクションで紹介するメソッドのいくつかは、OpenOptionパラメータを取ります。 このパラメータは任意であり、指定しない場合のメソッドのデフォルト動作はAPIの示すとおりです。

StandardOpenOption列挙型の次の定数がサポートされます。


小さなファイル用の一般的なメソッド

ファイルの全バイトまたは全行の読取り

小さめのファイルについて、1回渡すだけでその内容全体を読み取るには、readAllBytes(Path)メソッドまたはreadAllLines(Path, Charset)メソッドを使用できます。 これらのメソッドでは、ストリームのオープンやクローズなど、必要な処理のほとんどが行われますが、大きなファイルの処理は想定されていません。 readAllBytesメソッドは次のように使用します。

Path file = ...;
byte[] fileArray;
fileArray = Files.readAllBytes(file);

ファイルへの全バイトまたは全行の書込み

バイトまたは行をファイルに書き込む場合は、次のwriteメソッドのいずれかを使用できます。

writeメソッドは、次のように使用します。

Path file = ...;
byte[] buf = ...;
Files.write(file, buf);


テキスト・ファイル用バッファI/Oメソッド

java.nio.fileパッケージはチャネルI/Oをサポートしています。このI/Oでは、ストリームI/Oのボトルネックとなる可能性のある一部のレイヤーを経由せずに、バッファ内のデータを移動します。

バッファ・ストリームI/Oを使用したファイルの読取り

newBufferedReader(Path, Charset)メソッドは、ファイルを読取り用にオープンし、BufferedReaderを返します。これを使用して、ファイルからテキストを効率的に読み取ることができます。

次のコードでは、newBufferedReaderメソッドを使用してファイルからテキストを読み取っています。 ここでは、ファイルを"US-ASCII"でエンコードしています。

Charset charset = Charset.forName("US-ASCII");
try (BufferedReader reader = Files.newBufferedReader(file, charset)) {
    String line = null;
    while ((line = reader.readLine()) != null) {
	System.out.println(line);
    }
} catch (IOException x) {
	System.err.format("IOException: %s%n", x);
}

バッファ・ストリームI/Oを使用したファイルの書込み

newBufferedWriter(Path, Charset, OpenOption...)メソッドを使用して、BufferedWriterによるファイルへの書込みを行うことができます。

次のコードでは、このメソッドを使用して、"US-ASCII"でエンコードされたファイルを作成しています。

Charset charset = Charset.forName("US-ASCII");
String s = ...;
try (BufferedWriter writer = Files.newBufferedWriter(file, charset)) {
    writer.write(s, 0, s.length());
} catch (IOException x) {
    System.err.format("IOException: %s%n", x);
}


java.io APIとの相互運用性がある非バッファ・ストリーム用メソッド

ストリームI/Oを使用したファイルの読取り

ファイルを読取り用にオープンする場合は、newInputStream(Path, OpenOption...)メソッドを使用できます。 このメソッドは、ファイルからバイトを読み取るための非バッファ入力ストリームを返します。

Path file = ...;
try (InputStream in = Files.newInputStream(file);
     BufferedReader reader = new BufferedReader(new InputStreamReader(in))) {
    String line = null;
    while ((line = reader.readLine()) != null) {
        System.out.println(line);
    }
} catch (IOException x) {
    System.err.println(x);
}

ストリームI/Oを使用したファイルの作成と書込み

newOutputStream(Path, OpenOption...)メソッドを使用してファイルの作成、ファイルへのデータの追加、ファイルへの書込みを行うことができます。 このメソッドは、バイトの書込み用にファイルをオープンするか作成し、非バッファ出力ストリームを返します。

このメソッドは、任意のパラメータとしてOpenOptionを取ります。 OpenOptionとして何も指定されていない場合、ファイルが存在しなければ、新しいファイルが作成されます。 ファイルが存在するときは、そのファイルは切り詰められます。 この動作は、CREATEオプションとTRUNCATE_EXISTINGオプションを指定してメソッドを呼び出した場合の動作と同等になります。

次のコードでは、ログ・ファイルをオープンします。 ファイルが存在しない場合は、作成されます。 ファイルが存在する場合は、データを追加するためにファイルがオープンされます。

import static java.nio.file.StandardOpenOption.*;

Path logfile = ...;

//文字列をバイト配列に変換します。
String s = ...;
byte data[] = s.getBytes();

try (OutputStream out = new BufferedOutputStream(logfile.newOutputStream(CREATE, APPEND))) {
    ...
    out.write(data, 0, data.length);
} catch (IOException x) {
    System.err.println(x);
}


チャネル用メソッドやByteBuffer用メソッド

チャネルI/Oを使用したファイルの読取りと書込み

ストリームI/Oは1文字ずつ読み取りますが、チャネルI/Oは1バッファずつ読み取ります。 ByteChannelインタフェースには、基本的なreadおよびwriteの機能が用意されています。 SeekableByteChannelは、チャネル内の位置を保持し、その位置を変更する機能を持つByteChannelです。 SeekableByteChannelは、チャネルに関連するファイルの切詰めと、ファイルのサイズに関する問合せもサポートしています。

ファイル内の異なる場所に移動し、その位置から読み取る、またはその位置に書き込む機能によって、ファイルのランダム・アクセスが可能になります。 詳細は、『ランダム・アクセス・ファイル』を参照してください。

チャネルI/Oの読取りと書込みのためのメソッドは2つあります。


注:newByteChannelメソッドは、SeekableByteChannelのインスタンスを返します。 デフォルトのファイル・システムでは、このシーク可能なバイト・チャネルをFileChannelにキャストできます。このキャストによって、ファイルのある領域をメモリに直接マップしてアクセスを高速化する、ファイルのある領域をロックして他のプロセスがアクセスできないようにする、チャネルの現在の位置に影響を及ぼさずに絶対位置からのバイトの読取りや書込みを行うといった、より高度な機能を利用できるようになります。

両方のnewByteChannelメソッドで、OpenOptionのオプション・リストを指定できます。 newOutputStreamメソッドで使用されるものと同じOpenOptionを使用できますが、これに加えてもう1つ、READがサポートされます。SeekableByteChannelは読取りと書込みの両方に対応しているため、READが必要となります。

READを指定すると、チャネルが読取り用にオープンされます。 WRITEまたはAPPENDを指定すると、チャネルは書込み用にオープンされます。 これらのオプションを指定しない場合は、チャネルは読取り用にオープンされます。

次のコードでは、ファイルを読み取って、標準出力に出力します。

//デフォルトはREAD
try (SeekableByteChannel sbc = Files.newByteChannel(file)) {
    ByteBuffer buf = ByteBuffer.allocate(10);

    //このプラットフォームに適したエンコードを指定してバイトを読み取ります。
    //この手順を行わないと、ラテン系の文字を想定しているときに
    //中国語のような文字が表示されることがあります。
    String encoding = System.getProperty("file.encoding");
    while (sbc.read(buf) > 0) {
        buf.rewind();
        System.out.print(Charset.forName(encoding).decode(buf));
        buf.flip();
    }
} catch (IOException x) {
    System.out.println("caught exception: " + x);

UNIXなどのPOSIXファイル・システム向けに記述された次のコードでは、特定の権限セットを持つログ・ファイルを作成します。 このコードによって、ログ・ファイルが作成されるか、すでに存在する場合はログ・ファイルにデータが追加されます。 所有者には読取り/書込み権限、グループには読取り専用権限が付与されたログ・ファイルが作成されます。

import static java.nio.file.StandardCopyOption.*;

//ファイルにデータを追加するためのオプションのセットを作成します。
Set<OpenOptions> options = new HashSet<OpenOption>();
options.add(APPEND);
options.add(CREATE);

//カスタムの権限属性を作成します。
Set<PosixFilePermission> perms = PosixFilePermissions.fromString("rw-r------");
FileAttribute<Set<PosixFilePermission>> attr = PosixFilePermissions.asFileAttribute(perms);

//文字列をByteBufferに変換します。
String s = ...;
byte data[] = s.getBytes();
ByteBuffer bb = ByteBuffer.wrap(data);

try (SeekableByteChannel sbc = Files.newByteChannel(file, options, attr)) {
    sbc.write(bb);
} catch (IOException x) {
    System.out.println("exception thrown: " + x);
}


通常のファイルおよび一時ファイルの作成用メソッド

ファイルの作成

createFile(Path, FileAttribute<?>)メソッドを使用して、初期属性セットを持つ空のファイルを作成できます。 たとえば、作成時に特定のファイル権限セットを設定する場合は、createFileメソッドを使用します。 属性を指定しない場合は、デフォルトの属性を持つファイルが作成されます。 ファイルがすでに存在する場合は、createFileは例外をスローします。

1つの原子的な操作の中で、createFileメソッドはファイルの存在を確認し、指定した属性を持つファイルを作成します。これによって、悪意のあるコードに対してプロセスがよりセキュアになります。

次のコードでは、デフォルトの属性を持つファイルを作成します。

Path file = ...;
try {
    Files.createFile(file);   //デフォルト権限などを持つ空のファイルを作成します。
} catch (FileAlreadyExistsException x) {
    System.err.format("file named %s already exists%n", file);
} catch (IOException x) {
    //権限に関するエラーなど、その他の種類のエラーです。
    System.err.format("createFile error: %s%n", x);
}

POSIXファイル権限』に、createFile(Path, FileAttribute<?>)を使用して事前設定済みの権限を持つファイルを作成するサンプル・コードが記載されています。

また、『ストリームI/Oを使用したファイルの作成と書込み』で説明したとおり、newOutputStreamメソッドを使用して新しいファイルを作成することもできます。 新しい出力ストリームをオープンしすぐにクローズした場合は、空のファイルが作成されます。

一時ファイルの作成

次のいずれかのcreateTempFileメソッドを使用して、一時ファイルを作成できます。

1つ目のメソッドでは、一時ファイルのディレクトリを指定できます。2つ目のメソッドでは、デフォルトの一時ファイル・ディレクトリに新しいファイルを作成できます。 両方のメソッドとも、ファイル名の接尾辞を指定でき、さらに1つ目のメソッドでは接頭辞も指定できます。 次のコードでは、2つ目のメソッドを使用しています。

try {
    Path tempFile = Files.createTempFile(null, ".myapp");
    System.out.format("The temporary file has been created: %s%n", tempFile)
;
} catch (IOException x) {
    System.err.format("IOException: %s%n", x);
}

このファイルを実行すると、次のような結果となります。

The temporary file has been created: /tmp/509668702974537184.myapp
一時ファイル名の固有の形式はプラットフォームによって異なります。

サンプル・プログラムで問題が発生した場合は、 『Compiling and Running the Examples: FAQs』を参照してください。
フィードバックをお寄せください。さまざまなご意見をお待ちしております。

前のページ: メタデータの管理(ファイル属性とファイル・ストア属性)
次のページ: ランダム・アクセス・ファイル