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

図の左端に位置するのは、ユーティリティ・メソッドであるreadAllBytes、readAllLines、writeです。これらは一般的なケースで使用するために設計された単純なメソッドです。 その右には、newBufferedReaderやnewBufferedWriter、さらにnewInputStreamやnewOutputStreamなど、ストリームやテキスト行の反復処理に使用するメソッドが続きます。 これらのメソッドは、java.ioパッケージとの相互運用性があります。 さらにその右には、newByteChannelメソッドなどの、ByteChannel、SeekableByteChannel、ByteBufferを扱うメソッドがあります。 最後に、右端には、FileChannelを使用するメソッドが位置します。これらのメソッドは、ファイルのロックやメモリマップI/Oなどを必要とする高度なアプリケーションで使用します。
このページでは次のトピックについて説明します。
OpenOptionパラメータjava.io APIとの相互運用性がある非バッファ・ストリーム用メソッドByteBuffer用メソッド
OpenOptionパラメータ
このセクションで紹介するメソッドのいくつかは、OpenOptionパラメータを取ります。 このパラメータは任意であり、指定しない場合のメソッドのデフォルト動作はAPIの示すとおりです。
StandardOpenOption列挙型の次の定数がサポートされます。
WRITE – ファイルを書込みアクセス用にオープンします。
APPEND – ファイルの最後に新しいデータを追加します。 このオプションは、WRITEオプションまたはCREATEオプションとともに使用します。
TRUNCATE_EXISTING – ファイルを0バイトに切り詰めます。 このオプションは、WRITEオプションとともに使用します。
CREATE_NEW – 新しいファイルを作成し、ファイルがすでに存在する場合は例外をスローします。
CREATE – ファイルが存在する場合はオープンし、存在しない場合は新しいファイルを作成します。
DELETE_ON_CLOSE – ストリームのクローズ時にファイルを削除します。 このオプションは一時ファイルに使用すると便利です。
SPARSE – 新規に作成するファイルがスパース・ファイルであることを示します。 この高度なオプションは、データに空白の部分がある(スパース)大きなファイルを保存する際に、この空白部分にディスク領域を割り当てないことで効率的に保存できる、NTFSなどの一部のファイル・システムで重視されます。
SYNC – ファイル(内容とメタデータの両方)と、基盤となるストレージ・デバイスとの同期を維持します。
DSYNC – ファイルの内容と、基盤となるストレージ・デバイスとの同期を維持します。
小さめのファイルについて、1回渡すだけでその内容全体を読み取るには、readAllBytes(Path)メソッドまたはreadAllLines(Path, Charset)メソッドを使用できます。 これらのメソッドでは、ストリームのオープンやクローズなど、必要な処理のほとんどが行われますが、大きなファイルの処理は想定されていません。 readAllBytesメソッドは次のように使用します。
Path file = ...; byte[] fileArray; fileArray = Files.readAllBytes(file);
バイトまたは行をファイルに書き込む場合は、次のwriteメソッドのいずれかを使用できます。
write(Path, byte[], OpenOption...)write(Path, Iterable< extends CharSequence>, Charset, OpenOption...)
writeメソッドは、次のように使用します。
Path file = ...; byte[] buf = ...; Files.write(file, buf);
java.nio.fileパッケージはチャネル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);
}
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との相互運用性がある非バッファ・ストリーム用メソッド
ファイルを読取り用にオープンする場合は、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);
}
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は1文字ずつ読み取りますが、チャネルI/Oは1バッファずつ読み取ります。 ByteChannelインタフェースには、基本的なreadおよびwriteの機能が用意されています。 SeekableByteChannelは、チャネル内の位置を保持し、その位置を変更する機能を持つByteChannelです。 SeekableByteChannelは、チャネルに関連するファイルの切詰めと、ファイルのサイズに関する問合せもサポートしています。
ファイル内の異なる場所に移動し、その位置から読み取る、またはその位置に書き込む機能によって、ファイルのランダム・アクセスが可能になります。 詳細は、『ランダム・アクセス・ファイル』を参照してください。
チャネルI/Oの読取りと書込みのためのメソッドは2つあります。
newByteChannel(Path, OpenOption...)newByteChannel(Path, Set<? extends OpenOption>, FileAttribute<?>...)
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メソッドを使用して、一時ファイルを作成できます。
createTempFile(Path, String, String, FileAttribute<?>)createTempFile(String, String, FileAttribute<?>)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