Java のファイル入出力をざっくり一言でいうと
Java の「ファイル入出力(I/O)」は、
「ディスク上のファイルに、プログラムから文字やバイトを読み書きするための仕組み」
です。
初心者のうちに、まず次のイメージを持ってほしいです。
- 「ファイル」とやり取りするには、まず「どのファイルか」を表すオブジェクト(
PathやFile)が必要 - 読み込みは「入力ストリーム(Input)」、書き込みは「出力ストリーム(Output)」を使う
- 文字を扱うか、バイト(生データ)を扱うかでクラスが変わる
- 処理が終わったら、必ず「閉じる」(close)必要がある → これを安全にやる仕組みが
try-with-resources
ここを押さえれば、あとは「どう読みたいか(全部?1行ずつ?)」「何を書きたいか」を選ぶだけです。
ファイルを指し示すもの:Path と File の基本
Path(Java 7 以降の新しいやり方)
今の Java では、基本的に java.nio.file.Path を使うのがおすすめです。
import java.nio.file.Path;
import java.nio.file.Paths;
public class PathBasic {
public static void main(String[] args) {
Path path1 = Paths.get("data.txt"); // 相対パス
Path path2 = Paths.get("C:", "temp", "data.txt"); // Windows など
Path path3 = Paths.get("/home/user/data.txt"); // Unix 系
System.out.println(path1.toAbsolutePath());
}
}
JavaPath は「ファイル(またはディレクトリ)までの“道”」を表すだけで、
まだ開いたり読んだりはしていません。
Files クラス(後で出てきます)と組み合わせて、
- ファイルが存在するか
- 読み込む
- 書き込む
などを行います。
File(古いけどまだよく見る)
java.io.File も同じく「ファイルの場所」を表しますが、
File は古い API なので、新しく書くコードでは Path を優先して OK です。
ただし、既存ライブラリやサンプルコードではいまだによく出てきます。
import java.io.File;
File f = new File("data.txt");
System.out.println(f.getAbsolutePath());
System.out.println(f.exists());
Java頭の中では、
Path/Fileは「ファイルを指す“住所”」- 実際の読み書きは別クラスで行う
と整理しておいてください。
文字を「まとめて」読む・書く:Files クラス(高レベル API)
テキストファイルをすべて読み込む(小さいファイル向け)
java.nio.file.Files は、Path を使った便利メソッド集です。
小さいテキストファイルなら、一行で全部読み込めます。
import java.nio.file.Files;
import java.nio.file.Path;
import java.io.IOException;
import java.util.List;
public class ReadAllLinesExample {
public static void main(String[] args) throws IOException {
Path path = Path.of("data.txt");
List<String> lines = Files.readAllLines(path); // 1行ごとに List に入る
for (String line : lines) {
System.out.println(line);
}
}
}
JavaFiles.readAllLines は、「テキストファイルを全行読み込んで List<String> にして返す」メソッドです。
ファイルサイズが小さければ、これだけで済む場面はかなり多いです。
(巨大ファイルだとメモリに乗り切らないので注意)
テキストを丸ごと 1 つの文字列として読み込む
import java.nio.file.Files;
import java.nio.file.Path;
import java.io.IOException;
public class ReadStringExample {
public static void main(String[] args) throws IOException {
Path path = Path.of("data.txt");
String content = Files.readString(path); // ファイル全体を1つの文字列に
System.out.println(content);
}
}
Java設定ファイルやテンプレートを丸読みしたいときに便利です。
テキストを書き込む(ファイル作成・上書き)
import java.nio.file.Files;
import java.nio.file.Path;
import java.io.IOException;
import java.util.List;
public class WriteExample {
public static void main(String[] args) throws IOException {
Path path = Path.of("output.txt");
Files.writeString(path, "1行目\n2行目\n");
// 行のリストを書き込むこともできる
List<String> lines = List.of("Alice", "Bob", "Carol");
Files.write(path, lines); // OS のデフォルト文字コードで書き込み
}
}
JavaFiles.writeString や Files.write は、デフォルトでは既存ファイルを上書きします。
追記したいときはオプションを渡す必要がありますが、まずは「上書き」だけ覚えておけば十分です。
try-with-resources とストリーム系クラス(低レベル API の基本)
「開けたら必ず閉じる」を自動化する try-with-resources
ファイルを読む時も書く時も、「開いたら close する」が鉄則です。
それを安全に、漏れなくやるための構文が try-with-resources です。
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class TryWithResourcesExample {
public static void main(String[] args) {
try (BufferedReader reader = new BufferedReader(new FileReader("data.txt"))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
} // try ブロックを抜けると、自動で reader.close() が呼ばれる
}
}
Javatry (...) { ... } の丸カッコ内で作ったリソースは、
ブロックを抜けるときに自動で close() してくれます。
ファイル I/O では、try-with-resources を使うのが標準的な書き方です。
Reader / Writer と InputStream / OutputStream の違い
Java の I/O には、大きく 2 系統あります。
文字ベース(テキスト)
…… Reader / Writer の世界。文字コード(UTF-8 など)を意識する。
バイトベース(生データ)
…… InputStream / OutputStream の世界。画像・音声・バイナリファイルなど。
テキストファイルなら Reader / Writer を、
バイナリファイルなら InputStream / OutputStream を使う、というイメージです。
テキストファイルを 1 行ずつ読む基本パターン(Reader)
BufferedReader + FileReader の定番形
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class ReadLineByLine {
public static void main(String[] args) {
try (BufferedReader reader = new BufferedReader(new FileReader("data.txt"))) {
String line;
while ((line = reader.readLine()) != null) { // 1行ずつ読み込む
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Javaここでやっていることは、
FileReaderでファイルを開く(文字として読む前提)BufferedReaderで「まとめ読み」して効率を良くするreadLine()で 1 行ずつ取り出す- 最後に自動で close
という流れです。
「ファイルを 1 行ずつ処理したい」という場面では、このパターンはよく使います。
(最近は Files.lines(Path) で Stream として読む方法もあります)
テキストファイルに書き込む基本パターン(Writer)
BufferedWriter + FileWriter の定番形
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class WriteLines {
public static void main(String[] args) {
try (BufferedWriter writer = new BufferedWriter(new FileWriter("output.txt"))) {
writer.write("1行目");
writer.newLine(); // 改行
writer.write("2行目");
writer.newLine();
} catch (IOException e) {
e.printStackTrace();
} // 自動で close & flush
}
}
Javaポイントは、
writeで文字列を書くnewLine()で OS に合った改行コードを書く- try-with-resources により、最後に自動で flush & close
というところです。
「ログを書き出す」「結果をテキストで保存する」など、
実務で出番が多い形です。
バイナリファイルの読み書き(InputStream / OutputStream)
画像・PDF など「生データ」をそのままコピーする
画像ファイルを別名でコピーする例です。
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyBinaryFile {
public static void main(String[] args) {
try (FileInputStream in = new FileInputStream("input.png");
FileOutputStream out = new FileOutputStream("output.png")) {
byte[] buffer = new byte[8192]; // 8KB のバッファ
int len;
while ((len = in.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Javaここでは、
byte[]の配列で「生データ」を読み書きしている- テキストではないので、文字コードは一切意識しない
というのが重要です。
テキストなのかバイナリなのかで、
「Reader/Writer を使うか」「InputStream/OutputStream を使うか」が変わる、という感覚を持ってください。
エンコーディング(文字コード)について一言だけ
テキストファイルを扱うとき、「文字コード(UTF-8, Shift_JIS など)」はとても重要です。
Files.readAllLines や FileReader などは、デフォルトだと「プラットフォームのデフォルト文字コード」を使います。
(Windows なら CP932 だったり、Linux なら UTF-8 だったり)
文字化けを確実に避けたいなら、明示的にエンコーディングを指定する習慣を付けるといいです。
例として、UTF-8 で読む:
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.io.IOException;
import java.util.List;
public class ReadUtf8 {
public static void main(String[] args) throws IOException {
Path path = Path.of("data.txt");
List<String> lines = Files.readAllLines(path, StandardCharsets.UTF_8);
}
}
Java同様に、書き込みも UTF-8 を指定できます。
最初は「UTF-8 を明示しておく」と覚えておくのがおすすめです。
まとめ:ファイル入出力を自分の中でこう整理する
Java のファイル入出力の概要を、初心者向けに整理するとこうなります。
- どのファイルかは
Path/Fileで表す(新規コードは基本Path) - 小さいテキストなら
Files.readAllLines/readString/writeStringで一発読み書き - より細かく制御したいときは、Reader/Writer(テキスト)か InputStream/OutputStream(バイナリ)を使う
- リソースは
try-with-resourcesで自動 close するのが標準 - 「テキスト vs バイナリ」「エンコーディング(文字コード)が何か」を意識することが重要
