Java nio の API を見ていくシリーズ(目次)。 今回はファイルに対しての読み書きを行うメソッドを見ていきます。 Files クラスのメソッドで一番使うものかも知れませんね。
Files クラスには、いろいろな方法でファイルに読み書きするメソッドが定義されてます。 大別すれば「バイト」と「文字」の読み書きですが、これは java.io パッケージのクラスで言うと InputStream/OutputStream と Reader/Writer に対応するものです*1。 それぞれの読み書きにも更に幾つかの方法があります:
- バイトの読み書き
- 文字列の読み書き
- 文字列 (小さいファイル用)
- 文字ストリーム
- Java8 Stream API
以下でそれぞれを見ていきます。 更に上記の幾つかのメソッドで指定できる OpenOption についても見ていきます:
参考
- The Java Tutorial 「Reading, Writing, and Creating Files」
Files クラスの宣言
まずは java.nio.file.Files クラスに定義されている、ファイルの読み書きに関する static メソッドには以下のようなものがあります:package java.nio.file; public final Class Files{ ... // 読み書き可能? public static boolean isReadable(Path path) public static boolean isWritable(Path path) // ***** Byte IO ***** // バイト配列 public static byte[] readAllBytes(Path path) public static Path write(Path path, byte[] bytes, OpenOption... options) // バイト・ストリーム public static InputStream newInputStream(Path path, OpenOption... options) public static OutputStream newOutputStream(Path path, OpenOption... options) // バイト・チャネル public static SeekableByteChannel newByteChannel(Path path, OpenOption... options) public static SeekableByteChannel newByteChannel( Path path, Set<? extends OpenOption> options, FileAttribute<?>... attrs) // ***** 文字列 ***** // 文字列 public static List<String> readAllLines(Path path, Charset cs) public static Path write( Path path, Iterable<? extends CharSequence> lines, Charset cs, OpenOption... options) // 文字ストリーム public static BufferedReader newBufferedReader(Path path, Charset cs) public static BufferedWriter newBufferedWriter(Path path, Charset cs, OpenOption... options) // 【New】Java8 Stream API static Stream<String> lines(Path path) static Stream<String> lines(Path path, Charset cs) }
以下のサンプルでは使ってませんが、引数のファイルが読み書き可能かどうかをテストするメソッドがあります:
メソッド | 返り値 | 説明 |
---|---|---|
isReadable(Path) | boolean | 指定したファイルが読み込みできるかどうかをテスト |
isWritable(Path) | boolean | 指定したファイルが書き込みできるかどうかをテスト |
バイトの読み書き
バイトベースの読み書きを行うメソッドを見ていきましょう。 これには3種類あります:- バイト配列
- バイト・ストリーム
- バイト・チャネル
バイト配列
読み書きを行うメソッドは以下の通り:メソッド | 返り値 | 説明 |
---|---|---|
readAllBytes(Path) | byte[] | ファイルの内容をバイト配列として全て読み込む |
write(Path, byte[], OpenOption...) | Path | 引数のバイト配列をファイルへ書き出す |
これらは小さいファイルの読み書きに使ってください。 「source.txt」というファイルから内容を読み取って「dest1.txt」へ書き出すサンプル:
import java.io.IOException; import java.nio.file.*; public class ByteIO { public static void main(String... args)throws IOException{ Path src = Paths.get("source.txt"); byte[] bytes = Files.readAllBytes(src); // バイト配列へ読み込む System.out.println(new String(bytes)); Path dest = Paths.get("dest1.txt"); Files.write(dest, bytes); // バイト配列をファイルへ書き出す } }
- write() メソッドは、OpenOption が指定されていなければ CREATE, TRUNCATE_EXISTING, WRITE が指定されているのと同じになります
バイト・ストリーム
次はバイト・ストリームに対して読み書きするメソッド:メソッド | 返り値 | 説明 |
---|---|---|
newInputStream(Path, OpenOption...) | InputStream | 指定したファイルの内容を読み込む InputStream を返す |
newOutputStream(Path, OpenOption...) | OutputStream | 指定したファイルへ書き出す OutputStream を返す |
返り値の InputStream/OutputStream は、どちらも java.io パッケージのクラスです。
「source.txt」というファイルから内容を読み取って「dest2.txt」へ書き出すサンプル:
import java.io.*; import java.nio.file.*; public class ByteStreamIO { public static void main(String... args)throws IOException{ Path src = Paths.get("source.txt"); Path dest = Paths.get("dest2.txt"); try(InputStream in = Files.newInputStream(src); OutputStream out = Files.newOutputStream(dest)){ for(int c = in.read(); c != -1; c = in.read()){ // InputStream からの読み込み System.out.print((char)c); out.write((char)c); // OutputStream への書き出し } } } }
- 返される InputStream/OutputStream は通常の java.io パッケージのクラスで、使い方も同じです
- InputStream/OutputStream は使用後に close() メソッドで閉じる必要があります。 Java7 では try-with-resources 文で暗黙に閉じるのが普通でしょうけど
- newInputStream() メソッドは、OptionOption が指定されていない場合は、READ が指定されているのと同じです
- newOutputStream() メソッドは、OpenOption が指定されていなければ CREATE, TRUNCATE_EXISTING, WRITE が指定されているのと同じになります
バイト・チャネル
メソッド | 返り値 | 説明 |
---|---|---|
newByteChannel(Path, OpenOption...) newByteChannel(Path, Set, FileAttribute...) |
SeekableByteChannel | 指定したファイルに対するバイト・チャネルを返す |
返り値の SeekableByteChannel は java.nio.channels パッケージのクラスです。 このクラスは通常 FileChannel にキャストできるそうです。 なぜ返り値がそうなってないのかは分かりませんが・・・ また、バイト・チャネルには読み書きを分けて返すメソッドがないので、バイト・チャネルに書き出したい場合は OpenOption を指定する必要があります。 下記のサンプル参照。
「source.txt」というファイルから内容を読み取って「dest3.txt」へ書き出すサンプル:
import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.file.*; import static java.nio.file.StandardOpenOption.*; public class ByteChannelIO { public static void main(String... args)throws IOException{ Path src = Paths.get("source.txt"); Path dest = Paths.get("dest3.txt"); try(FileChannel inCh = (FileChannel)Files.newByteChannel(src); // 返り値は FileChannel。 別にキャストしなくても OK FileChannel outCh = (FileChannel)Files.newByteChannel(dest, CREATE, TRUNCATE_EXISTING, WRITE)){ // バイト・チャネルに書き出すためには、OpenOption に少なくとも StandardOpenOption.WRITE を指定する必要あり ByteBuffer buf = ByteBuffer.allocate((int)inCh.size()); inCh.read(buf); // バイト・チャネル inCh から buf へ読み込む String s = new String(buf.array()); System.out.print(s); outCh.write(ByteBuffer.wrap(s.getBytes())); // String → byte[] → ByteBuffer と変換して outCh へ書き出し } } }
- ByteChannel, ByteBuffer などの使い方はそれぞれの JavaDoc などを参照してください
- バイト・チャネルに書き出したい場合は、newByteChannel() メソッドの OpenOption に StandardOpenOption.WRITE を指定する必要があります
文字列の読み書き
次は文字列の読み書きをするメソッド。 読み書き対象のファイルを指定する Path オブジェクトに加えて、エンコーディングを行っているキャラクターセット (java.nio.charset.Charset オブジェクト)を指定する必要があります。文字列
まずはファイル内の各行を String オブジェクトとして読み書きするメソッド:メソッド | 返り値 | 説明 |
---|---|---|
readAllLines(Path, Charset) | List |
ファイル内の各行を String オブジェクトとして読み取る |
write(Path, Iterable, Charset, OpenOption...) | Path | 各 CharSequence を行としてファイルへ書き出す |
write() メソッドの引数にある CharSequence クラスは、とりあえず String オブジェクトと思って構いません。 「Iterable<? extends CharSequence>」は例えば「List<String>」などが型としてマッチします。 また、バイト配列の読み書きに使った readAllBytes()/write() メソッド同様、これらのメソッドは小さいファイルに対して使うようにしてください。
「source.txt」というファイルから内容を読み取って「dest4.txt」へ書き出すサンプル:
import java.io.IOException; import java.nio.charset.Charset; import java.nio.file.*; import java.util.List; public class StringIO { public static void main(String... args)throws IOException{ Path src = Paths.get("source.txt"); List<String> lines = Files.readAllLines(src, Charset.defaultCharset()); // ファイル内容の読み込み for(String line : lines){ System.out.println(line); } Path dest = Paths.get("dest4.txt"); Files.write(dest, lines, Charset.forName("UTF-8")); // ファイル内容の書き出し } }
- ファイルシステムのデフォルト Charset を取得するには Charset#defaultCharset() メソッドを用います
- 名前を指定して Charaset オブジェクトを取得したい場合は Charset#forName(String) メソッドを用います
- write() メソッドは、OpenOption が指定されていなければ CREATE, TRUNCATE_EXISTING, WRITE が指定されているのと同じになります
文字ストリーム
メソッド | 返り値 | 説明 |
---|---|---|
newBufferedReader(Path, Charset) | java.io.BufferedReader | 指定したファイルから内容を読み込む BufferedReader を返す |
newBufferedWriter(Path, Charset, OpenOption...) | java.io.BufferedWriter | 指定したファイルへ書き出す BufferedWriter を返す |
返り値の BufferedReader/BufferedWriter は、 java.io パッケージのいつものクラスです。
「source.txt」というファイルから内容を読み取って「dest5.txt」へ書き出すサンプル:
import java.io.*; import java.nio.charset.Charset; import java.nio.file.*; public class CharacterStreamIO { public static void main(String... args)throws IOException{ Path src = Paths.get("source.txt"); Path dest = Paths.get("dest5.txt"); try(BufferedReader reader = Files.newBufferedReader(src, Charset.defaultCharset()); BufferedWriter writer = Files.newBufferedWriter(dest, Charset.defaultCharset())){ for(String line = reader.readLine(); line != null; line = reader.readLine()){ // ファイル内容の読み込み System.out.println(line); writer.write(line); // ファイルへの書き出し writer.newLine(); } } } }
- BufferedReader/BufferedWriter は普通に使ってください。 使用後は close() メソッドによって閉じる必要があります。 ここでは try-with-resources 文によって close 処理を行っています
- newBuffered
ReaderWriter() メソッドは、OpenOption が指定されていなければ CREATE, TRUNCATE_EXISTING, WRITE が指定されているのと同じになります
OpenOption インターフェース
最後に OpenOption インターフェースについて。 OpenOption インターフェースを実装しているクラスは以下の2つ:- LinkOption
- StandardOpenOption
これらはどちらも列挙型 (enum) です。 LinkOption 定数は前回やりました。 なので、ここでは StandardOpenOption についてのみ見ていきます。 StandardOpenOption の定義は以下の通り:
package java.nio.file; public enum StandardOpenOption extends Enum<StandardOpenOption> implements OpenOption{ READ, WRITE, APPEND, TRUNCATE_EXISTING, CREATE_NEW, CREATE, DELETE_ON_CLOSE, SPARSE, SYNC, DSYNC }
それぞれの定数の意味は
定数 | 説明 |
---|---|
READ | 読み込み可能として開く |
WRITE | 書き込み可能として開く |
APPEND | ファイルの末尾に内容を追加する。 WRITE または CREATE とともに用いる |
TRUNCATE_EXISTING | ファイル内容を最初から書き込む。 WRITE とともに用いる |
CREATE_NEW | ファイルを新たに作って開く。 もしファイルがあれば例外を投げる |
CREATE | ファイルを新たに作って開く。 もしあればそのまま開く |
DELETE_ON_CLOSE | ストリームが閉じられれば、そのファイルを削除する |
SPARSE | |
SYNC | ファイル内容とメタデータを同期化 |
DSYNC | ファイル内容を同期化 |
詳しくは以下を参照:
- The Java Tutorial 「Reading, Writing, and Creating Files」 The OpenOptions Parameter
- JavaDoc 「StandardOpenOption」
上記で見た Files メソッドのいろいろな書き込みメソッドで、OpenOption を指定しなかった場合のデフォルトであるCREATE, TRUNCATE_EXISTING, WRITE」というのは、「ファイルがなければ作成し、あれば内容を上書きする」と言う設定になります。
【追記】 Java8 で Files に追加されたファイル内容の読み書きメソッド lines
Java8 で Stream API が追加されたので、Files オブジェクトにも Stream 返すメソッドが追加定義されてます。 ただし、使う際には Stream を閉じるのを忘れずに。 通常 try-with-resources 文と一緒に使います。import java.nio.file.*; import java.nio.charset.StandardCharsets; import static java.util.Arrays.asList; import java.util.stream.Stream; public class FilesStreamTest { public static void main(String... args)throws Exception { // 準備 Path path = Files.createTempFile(null, null); Files.write(path, asList("first line.", "second line.", "third line.")); // Files#lines(path) try(Stream<String> lines = Files.lines(path)){ lines.forEach(System.out::println); // 「first line. // second line. // third line.」と表示 } // Files#lines(Path, Charset) // エンコーディングの指定 try(Stream<String> lines = Files.lines(path, StandardCharsets.UTF_8)){ lines.forEach(System.out::println); // 先ほどと同じ出力 } } }
文字エンコーディングを指定しなかった場合は UTF-8 が指定されたものとみなされます。

- 作者: 関谷和愛,上原潤二,須江信洋,中野靖治
- 出版社/メーカー: 技術評論社
- 発売日: 2011/07/06
- メディア: 単行本(ソフトカバー)
- 購入: 6人 クリック: 392回
- この商品を含むブログ (155件) を見る