Java | Java 標準ライブラリ:ファイル入出力概要

Java Java
スポンサーリンク

Java のファイル入出力をざっくり一言でいうと

Java の「ファイル入出力(I/O)」は、

「ディスク上のファイルに、プログラムから文字やバイトを読み書きするための仕組み

です。

初心者のうちに、まず次のイメージを持ってほしいです。

  • 「ファイル」とやり取りするには、まず「どのファイルか」を表すオブジェクト(PathFile)が必要
  • 読み込みは「入力ストリーム(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());
    }
}
Java

Path は「ファイル(またはディレクトリ)までの“道”」を表すだけで、
まだ開いたり読んだりはしていません。

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);
        }
    }
}
Java

Files.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 のデフォルト文字コードで書き込み
    }
}
Java

Files.writeStringFiles.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() が呼ばれる
    }
}
Java

try (...) { ... } の丸カッコ内で作ったリソースは、
ブロックを抜けるときに自動で 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.readAllLinesFileReader などは、デフォルトだと「プラットフォームのデフォルト文字コード」を使います。
(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 バイナリ」「エンコーディング(文字コード)が何か」を意識することが重要

タイトルとURLをコピーしました