入出力
- I/O と NIO と NIO.2
- 自動クローズ(AutoCloseable)
- バイナリファイルを1バイトずつ読み込む
- バイナリファイルをすべて読み込む
- テキストファイルを1文字ずつ読み込む
- テキストファイルを1行ずつ読み込む
- テキストファイルを全行まとめて読み込む
- バイナリファイルにバイト列を書き込む
- テキストファイルに1行ずつ書き込む
- テキストファイルに複数行を書き込む
I/O と NIO と NIO.2
Java では元々 java.io.* に含まれる I/O ライブラリをサポートしてきましたが、Windows と Linux 系で扱いが異なったり、ファイル権限操作やシンボリックリンク操作に制約がありました。これを改善した NIO(New I/O) が java.nio.* でサポートされました。また、Java SE 7 からは NIO.2 と呼ばれるライブラリも追加され、大半は java.nio.file.* に含められています。現在では I/O(java.io.*) よりも NIO や NIO.2 (java.nio.*) を使用することが推奨されています。
自動クローズ(AutoCloseable)
古い書き方の場合、入出力に関するクラスの多くは使用が終わると close() する必要があります。
try {
FileReader in = new FileReader("file.txt");
:
in.close();
} catch (Exception e) {
e.printStackTrace();
}
入出力に関するクラスの大半は Java 7 でサポートされた AutoCloseable インタフェースを実装しており、下記の様に記述することで close() を省略することができます。
try (FileReader in = new FileReader("file.txt")) {
:
} catch (Exception e) {
e.printStackTrace();
}
バイナリファイルを1バイトずつ読み込む
FileInputStream (I/O)
バイナリファイルを1バイトずつ読み込みます。
import java.io.*;
class Main {
public static void main(String[] args) {
try (FileInputStream in = new FileInputStream("file.bin")) {
int ch;
while ((ch = in.read()) != -1) {
System.out.print(String.format("%02x ", Integer.valueOf(ch)));
}
System.out.println("");
} catch (Exception e) {
e.printStackTrace();
}
}
}
BufferedInputStream (I/O)
バイナリファイルを1バイトずつ読み込みます。FileInputStream() だけだとファイルから1バイトずつ読み取るのに対して、BufferedInputStream を用いると 8192 バイトずつバッファリングしながら読み込むため、高速に読み込むことができます。
import java.io.*;
class Main {
public static void main(String[] args) {
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("file.bin"))) {
int ch;
while ((ch = bis.read()) != -1) {
System.out.print(String.format("%02x ", Integer.valueOf(ch)));
}
System.out.println("");
} catch (Exception e) {
e.printStackTrace();
}
}
}
newInputStream (NIO)
バイナリファイルを1バイトずつ読み込みます。
import java.io.*;
import java.nio.file.*;
class Main {
public static void main(String[] args) {
Path path = Paths.get("file.bin");
try (InputStream is = Files.newInputStream(path)) {
int ch;
while ((ch = is.read()) != -1) {
System.out.print(String.format("%02x ", Integer.valueOf(ch)));
}
System.out.println("");
} catch (Exception e) {
e.printStackTrace();
}
}
}
バイナリファイルをすべて読み込む
readAllBytes (NIO)
バイナリファイルをバイト列としてすべて読み込みます。
import java.nio.file.*;
class Main {
public static void main(String[] args) {
Path path = Paths.get("file.bin");
try {
byte[] bytes = Files.readAllBytes(path);
for (byte by : bytes) {
System.out.print(String.format("%02x ", Integer.valueOf(0xFF & by)));
}
System.out.println("");
} catch (Exception e) {
e.printStackTrace();
}
}
}
テキストファイルを1文字ずつ読み込む
InputStreamReader (I/O)
テキストファイルを1文字ずつ読み込みます。
import java.io.*;
class Main {
public static void main(String[] args) {
try (InputStreamReader in = new InputStreamReader(new FileInputStream("file.txt"), "UTF-8")) {
int ch;
while ((ch = in.read()) != -1) {
System.out.print(String.format("%04x ", Integer.valueOf(ch)));
}
System.out.println("");
} catch (Exception e) {
e.printStackTrace();
}
}
}
UTF-8 の「あいう」という内容のファイルを読み込んだ場合、結果は次のようになります。3042 は「あ」、3044 は「い」、3046 は「う」の UTF-16 コードです。InputStreamReader を用いることで UTF-8 のファイルを Java の標準文字コードである UTF-16 に変換しながら読み込むことができました。
3042 3044 3046 000a
文字コードを省略した場合は、プラットフォームに依存したデフォルト(省略時の)文字コードで読み出されます。日本語 Windows の場合のデフォルト文字コードは MS932、Linux では UTF-8 になります。
FileReader (I/O)
InputStreamReader の面倒さを解消するために用意されたサブクラスです。InputStreamReader より簡単に扱えますが、文字コードを指定することができません。
import java.io.*;
class Main {
public static void main(String[] args) {
try (FileReader in = new FileReader("file.txt")) {
int ch;
while ((ch = in.read()) != -1) {
System.out.print(String.format("%04x ", Integer.valueOf(ch)));
}
System.out.println("");
} catch (Exception e) {
e.printStackTrace();
}
}
}
テキストファイルを1行ずつ読み込む
BufferedReader (I/O)
テキストファイルを1行ずつ読み込みます。
import java.io.*;
class Main {
public static void main(String[] args) {
try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Scanner (I/O)
テキストファイルを1行ずつ読み込みます。
import java.io.File;
import java.util.Scanner;
class Main {
public static void main(String[] args) {
try (Scanner in = new Scanner(new File("file.txt"))) {
while (in.hasNextLine()) {
String line = in.nextLine();
System.out.println(line);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
BufferedReader より若干遅いですが、下記の様にしてキーボードからの入力を読み込むことができます。
Scanner in = new Scanner(System.in);
newBufferedReader (NIO)
NIO では BufferedReader を簡単に使用するための newBufferedReader() をサポートしています。
import java.io.*;
import java.nio.file.*;
class Main {
public static void main(String[] args) {
Path path = Paths.get("file.txt");
try (BufferedReader br = Files.newBufferedReader(path)) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
ファイルの文字コードを指定することもできます。
Files.newBufferedReader(path, StandardCharsets.UTF_8))
Files.newBufferedReader(path, Charset.forName("MS932"))
lines (NIO)
テキストファイルを1行ずつ読み込みます。
import java.util.stream.Stream;
import java.nio.file.*;
class Main {
public static void main(String[] args) {
Path path = Paths.get("file.txt");
try (Stream<String> stream = Files.lines(path)) {
stream.forEach(line -> {
System.out.println(line);
});
} catch (Exception e) {
e.printStackTrace();
}
}
}
テキストファイルを全行まとめて読み込む
readAllLines (NIO)
ファイルの全行を行の配列として読み込みます。
import java.util.List;
import java.nio.file.*;
class Main {
public static void main(String[] args) {
Path path = Paths.get("file.txt");
try {
List<String>lines = Files.readAllLines(path);
for (String line : lines) {
System.out.println(line);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
バイナリファイルにバイト列を書き込む
BufferedOutputStream (NIO)
バイナリファイルにバイト列を書き込みます。
import java.io.*;
import java.nio.file.*;
class Main {
public static void main(String[] args) {
Path path = Paths.get("file.txt");
try (BufferedOutputStream bos = new BufferedOutputStream(Files.newOutputStream(path))) {
byte[] buf = { 0x41, 0x42, 0x43, 0x0a };
bos.write(buf);
} catch (Exception e) {
e.printStackTrace();
}
}
}
テキストファイルに1行ずつ書き込む
newBufferedWriter (NIO)
テキストファイルに1行ずつ書き込みます。
import java.io.*;
import java.nio.file.*;
class Main {
public static void main(String[] args) {
Path path = Paths.get("file.txt");
try (BufferedWriter bw = Files.newBufferedWriter(path)) {
String line = "This is Japan.\n";
bw.write(line);
} catch (Exception e) {
e.printStackTrace();
}
}
}
テキストファイルに複数行を書き込む
write (NIO)
テキストファイルに複数行まとめて書き込みます。
import java.util.List;
import java.nio.file.*;
import java.nio.charset.*;
class Main {
public static void main(String[] args) {
Path path = Paths.get("file.txt");
try {
List<String> lines = List.of("ABCDEFG", "HIJKLMN", "OPQRSTU");
Files.write(path, lines, StandardCharsets.UTF_8, StandardOpenOption.APPEND);
} catch (Exception e) {
e.printStackTrace();
}
}
}
第三引数には文字コードを指定します。省略すると OS 標準の文字コードとなります。第四引数以降(可変引数)には書込みオプションを指定します。
StandardOpenOption.APPEND 追記モードで書き込む StandardOpenOption.CREATE ファイルが存在しなければ作成する StandardOpenOption.CREATE_NEW ファイルが存在しなければ作成する。存在していればエラー StandardOpenOption.TRUNCATE_EXISTING ファイルが存在する場合は開いたときに0バイトにする StandardOpenOption.DELETE_ON_CLOSE ファイルを閉じる時に削除する StandardOpenOption.READ 読込みアクセス用に開く StandardOpenOption.WRITE 書込みアクセス用に開く StandardOpenOption.DSYNC 記憶装置に同期的に書き込む