Javaでファイル操作をマスターしよう!

docs

前回までの記事で、Javaプログラミングの基本を学んで、簡単なプログラムが書けるようになったはず。今回は、さらに一歩進んでファイル操作の基本を徹底解説するよ!

「ファイル操作って難しそう…」って思うかもしれないけど、Javaには便利なクラスがたくさん用意されているから大丈夫。この記事では、特にファイルの読み書きに使うFileInputStreamFileOutputStreamに焦点を当てて、具体的な例を交えながらわかりやすく説明していくね。


ファイルって何?

そもそもファイルって何だろう?みんなが普段使っているパソコンの中には、写真、音楽、文書など、いろんな種類のデータが保存されているよね。これらのデータは、ファイルという形で管理されているんだ。

Javaでプログラムを書いていると、「このデータをファイルに保存しておきたいな」とか、「ファイルに保存されているデータを読み込みたいな」って思うことがよくある。例えば、ユーザーが入力した情報を設定ファイルとして保存したり、ログファイルにプログラムの実行履歴を書き込んだりね。


ファイル操作の基本的な流れ

Javaでファイル操作を行うときは、基本的に次の流れで進めるよ。

  1. ファイルを開く(ストリームを作成する)
  2. データを読み書きする
  3. ファイルを閉じる(ストリームを閉じる)

この「ストリーム」っていうのがポイント。ストリームは、データが流れる道みたいなものだとイメージしてみて。ファイルからデータを読み込むときは「入力ストリーム」、ファイルにデータを書き込むときは「出力ストリーム」を使うんだ。


FileInputStreamでファイルを読み込んでみよう!

まずは、ファイルからデータを読み込む方法から見ていこう。使うのはFileInputStreamクラスだよ。

たとえば、sample.txtっていうファイルがあって、その中に「こんにちは、Java!」って書いてあるとしよう。この内容をJavaプログラムで読み込んで、画面に表示するにはどうすればいいかな?

Java

import java.io.FileInputStream;
import java.io.IOException;

public class FileReadExample {
    public static void main(String[] args) {
        // 読み込むファイルのパスを指定
        String filePath = "sample.txt"; // 同じディレクトリにある場合

        FileInputStream fis = null; // FileInputStreamオブジェクトを宣言
        try {
            // FileInputStreamを初期化(ファイルを開く)
            fis = new FileInputStream(filePath);

            int data; // 読み込んだデータを一時的に保存する変数
            System.out.println("ファイルの内容:");
            // ファイルの終わりに達するまで1バイトずつ読み込む
            while ((data = fis.read()) != -1) {
                System.out.print((char) data); // 読み込んだバイトを文字に変換して表示
            }
            System.out.println("\n--- ファイル読み込み完了 ---");

        } catch (IOException e) {
            // ファイルが見つからない、読み込みエラーなどが発生した場合
            System.err.println("ファイル読み込み中にエラーが発生しました: " + e.getMessage());
        } finally {
            // finallyブロックは、tryブロックが正常に終了しても、catchブロックが実行されても、必ず実行される
            // ここでFileInputStreamを閉じる
            if (fis != null) {
                try {
                    fis.close(); // ストリームを閉じる
                    System.out.println("FileInputStreamを閉じました。");
                } catch (IOException e) {
                    System.err.println("FileInputStreamを閉じる際にエラーが発生しました: " + e.getMessage());
                }
            }
        }
    }
}

このコードを解説していくね。

  • import java.io.FileInputStream;import java.io.IOException;: ファイル操作に必要なクラスをインポートしているよ。
  • String filePath = "sample.txt";: 読み込みたいファイルのパスを指定しているんだ。もしファイルがプログラムと同じディレクトリになければ、"C:/Users/YourName/Documents/sample.txt"のようにフルパスで指定する必要があるよ。
  • FileInputStream fis = null;: FileInputStreamクラスのオブジェクトを宣言している。tryブロックの外で宣言しているのは、finallyブロックでも使えるようにするためだよ。
  • try-catch-finally: ファイル操作では、**エラー(例外)**が発生する可能性が高いんだ。例えば、指定したファイルが見つからなかったり、ファイルが破損していたり。そんなときにプログラムが途中で止まってしまわないように、try-catchブロックでエラーを捕まえて(例外処理)、適切に対応するのがお作法だよ。
    • try: エラーが発生する可能性がある処理をここに書く。
    • catch (IOException e): tryブロック内でIOExceptionという種類のエラーが発生した場合に実行される。e.getMessage()でエラーの詳細な情報を取得できるよ。
    • finally: tryブロックが正常に終わっても、catchブロックが実行されても、必ず実行されるブロックなんだ。ここで、開いたストリームを確実に閉じる処理を書くのがとても重要だよ。ストリームを閉じないと、ファイルがロックされたままになったり、メモリリークの原因になったりすることがあるから気をつけよう。
  • fis = new FileInputStream(filePath);: ここでファイルを開いているんだ。指定したファイルが存在しないとFileNotFoundExceptionIOExceptionの一種)が発生するよ。
  • while ((data = fis.read()) != -1): ファイルからデータを読み込んでいる部分だよ。
    • fis.read(): ファイルから1バイトずつデータを読み込むメソッドなんだ。読み込むデータがもうないと-1を返すよ。
    • (char) data: read()メソッドはバイトデータを整数値で返すから、char型にキャスト(型変換)することで文字として表示しているんだ。

vscodeで実行した結果

FileOutputStreamでファイルに書き込んでみよう!

次に、Javaプログラムからファイルにデータを書き込む方法を見ていこう。使うのはFileOutputStreamクラスだよ。

例えば、「新しいファイルだよ!」っていう文字列をnew_file.txtというファイルに書き込んでみよう。

Java

import java.io.FileOutputStream;
import java.io.IOException;

public class FileWriteExample {
    public static void main(String[] args) {
        // 書き込むファイルのパスを指定
        String filePath = "new_file.txt";
        String content = "新しいファイルだよ!\nJavaで書き込みました。"; // 書き込む内容

        FileOutputStream fos = null; // FileOutputStreamオブジェクトを宣言
        try {
            // FileOutputStreamを初期化(ファイルを開く)
            // trueを渡すと追記モードになる。false(または省略)だと上書きモード。
            fos = new FileOutputStream(filePath);

            // 文字列をバイト配列に変換
            byte[] bytes = content.getBytes();

            // バイト配列をファイルに書き込む
            fos.write(bytes);

            System.out.println("ファイルに書き込みが完了しました: " + filePath);

        } catch (IOException e) {
            System.err.println("ファイル書き込み中にエラーが発生しました: " + e.getMessage());
        } finally {
            if (fos != null) {
                try {
                    fos.close(); // ストリームを閉じる
                    System.out.println("FileOutputStreamを閉じました。");
                } catch (IOException e) {
                    System.err.println("FileOutputStreamを閉じる際にエラーが発生しました: " + e.getMessage());
                }
            }
        }
    }
}

このコードも解説していくね。

  • String content = "新しいファイルだよ!\nJavaで書き込みました。";: ファイルに書き込みたい文字列を定義しているよ。\nは改行を意味する特殊文字だね。
  • fos = new FileOutputStream(filePath);: ここでファイルを開いているよ。
    • new FileOutputStream(filePath): これだと、もしnew_file.txtが既に存在したら、その内容は上書きされてしまうよ。
    • new FileOutputStream(filePath, true): もしファイルが既に存在する場合に、そのファイルの最後にデータを追記したいときは、このように第二引数にtrueを指定するんだ。覚えておくと便利だよ。
  • byte[] bytes = content.getBytes();: FileOutputStreamはバイトデータを扱うから、書き込みたい文字列をgetBytes()メソッドを使ってバイト配列に変換しているんだ。
  • fos.write(bytes);: バイト配列をファイルに書き込んでいるよ。

vscodeで実行した結果

もっと簡単にファイル操作!try-with-resources文

ここまででファイル操作の基本的な流れはわかったかな?でも、finallyブロックで毎回close()を書くのってちょっと面倒だよね。そこで、Java 7から導入されたtry-with-resourcesを使うと、もっとスマートに書けるようになるんだ!

try-with-resources文を使うと、tryの丸かっこ( )の中にストリームのオブジェクトを定義するだけで、自動的にストリームを閉じてくれるんだ。これ、めっちゃ便利!

さっきのファイル読み込みの例をtry-with-resources文で書き直してみるね。

Java

import java.io.FileInputStream;
import java.io.IOException;

public class FileReadWithResourcesExample {
    public static void main(String[] args) {
        String filePath = "sample.txt";

        // try-with-resources文を使ってFileInputStreamを自動で閉じる
        try (FileInputStream fis = new FileInputStream(filePath)) {
            int data;
            System.out.println("ファイルの内容:");
            while ((data = fis.read()) != -1) {
                System.out.print((char) data);
            }
            System.out.println("\n--- ファイル読み込み完了 ---");

        } catch (IOException e) {
            System.err.println("ファイル読み込み中にエラーが発生しました: " + e.getMessage());
        }
        System.out.println("FileInputStreamは自動的に閉じられました。"); // finallyブロックが不要に
    }
}

どう?すごくスッキリしたでしょ!finallyブロックがなくなって、コードの見通しがよくなったよね。ファイル書き込みも同じようにできるから、ぜひ使ってみてね。


vscodeで実行した結果

ファイル操作の注意点

ファイル操作をする上で、いくつか気をつけてほしいことがあるよ。

  • 例外処理は必ず行う!: 上で説明したtry-catch-finally(またはtry-with-resources)は絶対に必要だよ。ファイルが見つからない、書き込み権限がない、ディスクがいっぱい、といった様々な問題が発生する可能性があるからね。
  • ストリームは必ず閉じる!: close()メソッドを呼び出すか、try-with-resourcesを使うことで、開いたストリームは必ず閉じよう。これを怠ると、リソースの無駄遣いや、他のプログラムがファイルにアクセスできなくなるといった問題が起きることがあるよ。
  • パスの指定: ファイルのパスは正確に指定しよう。相対パス(sample.txt)はプログラムの実行ディレクトリからの相対的な位置、絶対パス(C:/users/foo/bar.txt)はシステムのルートからの位置を表すよ。
  • 文字コード: ファイルに書き込む文字や、ファイルから読み込む文字の文字コードにも注意が必要だよ。日本語を扱う場合は、UTF-8などの文字コードを意識しないと、文字化けが発生することがあるんだ。今回はシンプルなバイト単位の読み書きだったけど、文字として読み書きしたい場合は、後ほど紹介するリーダー・ライターを使うのが一般的だよ。

ファイル操作をもっと便利に!

今回はFileInputStreamFileOutputStreamを使って、バイト単位のファイル読み書きを学んだけど、Javaにはもっと高機能なファイル操作のためのクラスがたくさんあるんだ。

  • BufferedReader / BufferedWriter: 行単位でテキストファイルを読み書きするのに便利。特にテキストファイルを扱うなら、これらを使うのがおすすめ!
  • FileReader / FileWriter: 文字コードを意識したファイル読み書きができるよ。
  • Scanner: テキストファイルを読み込むのに、特に数値や文字列を解析しながら読み込みたい場合に便利。
  • Filesクラス(Java NIO.2): Java 7から導入された新しいAPIで、より直感的で高機能なファイル操作ができるよ。

これらのクラスについては、また別の記事で詳しく紹介するね。まずは今回の内容をしっかりマスターして、ファイル操作の基礎を固めよう!


まとめ

今回の記事では、Javaでのファイル操作の基本として、FileInputStreamFileOutputStreamを使ったファイルの読み書きについて解説したよ。

  • FileInputStream: ファイルからバイト単位でデータを読み込むときに使う。
  • FileOutputStream: ファイルにバイト単位でデータを書き込むときに使う。
  • ファイル操作では**例外処理(try-catch-finallyストリームを閉じること(close()またはtry-with-resources)**が超重要!

これで、君もJavaでファイルの読み書きができるようになったね!簡単なデータ保存やログ出力なんかも、これでバッチリできるはず。

もし途中で分からなくなったり、もっと詳しく知りたいことがあれば、他の記事(ToolDocs | 様々なツールや技術情報を紹介します )も参考にしながら、繰り返し練習してみてね。

コメント

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