0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Java入門 - 実践編】ファイルの操作

0
Posted at

はじめに

こんにちは。
スッキリわかるJava入門 実践編の学習を進めています。
この学習記録を備忘録として残しながら、自身の理解を深めたいと思っています。

今回は第2部 / 第6章「ファイルの操作」について学びました。
Javaにおけるストリームの基礎知識から、try-with-resources による安全なファイル入出力、そして Path/Files クラスを使った直感的なファイル操作までを学びました。

この記事が、同じくJavaの学習をしている人にとっても参考になりましたら幸いです。

参考書籍について

目次

  1. 本章の要点
  2. 自分なりの解釈

1. 本章の要点

ストリームの概念

ストリームとは、データの伝送路を表す概念で、JVMはストリームを通じてファイル、ネットワーク、キーボードなどのデータソースとやり取りします。

ファイル操作で主に使うストリームは、2つの種類に分けられます

  • 文字ストリーム:文字(Char)のデータが流れる。テキストファイルに最適。使用クラス:FileReader、FileWriter
  • バイトストリーム:バイト(byte)のデータが流れる。バイナリファイルや汎用的に使用。使用クラス:FileInputStream、FileOutputStream

ファイル操作の前提知識

ファイル操作は、「ファイルを開く」 → 「データを読み書きする」 → 「ファイルを閉じる」という3つのステップで構成されます。

Javaで扱うファイルには2つの種類があります

  • テキストファイル:人間が読める文字データで構成(.txt, .csv など)
  • バイナリファイル:バイト単位のデータで構成(.jpg, .exe など)

テキストファイルの読み書き

import java.io.*;

public class TextFileExample {
    // ファイルに書き込む
    public static void writeTextFile(String filename, String content) throws IOException {
        FileWriter writer = new FileWriter(filename);
        try {
            writer.write(content);
            System.out.println("ファイルに書き込みました:" + filename);
        } finally {
            writer.close();
        }
    }
    
    // ファイルから読み込む
    public static void readTextFile(String filename) throws IOException {
        FileReader reader = new FileReader(filename);
        try {
            int ch;
            StringBuilder sb = new StringBuilder();
            while ((ch = reader.read()) != -1) {
                sb.append((char) ch);
            }
            System.out.println("ファイル内容:");
            System.out.println(sb.toString());
        } finally {
            reader.close();
        }
    }
    
    public static void main(String[] args) throws IOException {
        // テキストファイルに書き込む
        String content = "ミナト\nアサカ\nシェナ";
        writeTextFile("heroes.txt", content);
        
        // テキストファイルから読み込む
        readTextFile("heroes.txt");
    }
}

バイナリファイルの読み書き

import java.io.*;

public class BinaryFileExample {
    // バイナリファイルに書き込む
    public static void writeBinaryFile(String filename, byte[] data) throws IOException {
        FileOutputStream stream = new FileOutputStream(filename);
        try {
            stream.write(data);
            System.out.println("バイナリファイルに書き込みました:" + filename);
        } finally {
            stream.close();
        }
    }
    
    // バイナリファイルから読み込む
    public static void readBinaryFile(String filename) throws IOException {
        FileInputStream stream = new FileInputStream(filename);
        try {
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = stream.read(buffer)) != -1) {
                System.out.println("読み込んだバイト数:" + bytesRead);
            }
        } finally {
            stream.close();
        }
    }
    
    public static void main(String[] args) throws IOException {
        // バイナリデータを作成
        byte[] data = new byte[] {
            0x89, 0x50, 0x4E, 0x47 // PNGファイルの識別子の例
        };
        
        // バイナリファイルに書き込む
        writeBinaryFile("sample.bin", data);
        
        // バイナリファイルから読み込む
        readBinaryFile("sample.bin");
    }
}

try-with-resourcesによる安全な例外処理

ファイルは必ずクローズしないといけません。try-with-resourcesを使うことで、例外が発生してもファイルが確実にクローズされます。

import java.io.*;
import java.nio.file.*;

public class SafeFileHandling {
    // try-with-resources文
    public static void safeWrite(String filename, String content) throws IOException {
        try (FileWriter writer = new FileWriter(filename)) {
            writer.write(content);
            System.out.println("安全に書き込みました");
        } // ここで自動的にクローズされる
    }
    
    // try-with-resources文で複数のリソースを扱う
    public static void safeReadAndWrite(String inputFile, String outputFile) throws IOException {
        try (FileReader reader = new FileReader(inputFile);
             FileWriter writer = new FileWriter(outputFile)) {
            
            int ch;
            while ((ch = reader.read()) != -1) {
                writer.write(ch);
            }
            System.out.println("ファイルをコピーしました");
        } // 両方のファイルが自動的にクローズされる
    }
    
    public static void main(String[] args) throws IOException {
        safeWrite("test.txt", "テスト内容");
        safeReadAndWrite("test.txt", "copy.txt");
    }
}

ファイルクローズが重要な理由

ファイルを閉じないと、以下の問題が発生します

  • メモリリーク(ファイルディスクリプタが消費される)
  • ファイルのロック(他のプロセスが操作できない)
  • データ喪失(バッファがフラッシュされない)

ファイルシステムの操作

java.io.Fileクラスは基本的なファイル操作ができますが、java.nio.FileとPath/Filesクラスでより高度で安全なファイルシステム操作が実現できます。

import java.io.*;
import java.nio.file.*;

public class FileSystemOperations {
    // 従来のFileクラス
    public static void legacyFileClass() {
        File file = new File("data.txt");
        
        // ファイルの存在確認
        System.out.println("存在するか:" + file.exists());
        
        // ファイルのサイズ
        System.out.println("ファイルサイズ:" + file.length() + " バイト");
        
        // ファイルの削除
        if (file.exists()) {
            file.delete();
            System.out.println("ファイルを削除しました");
        }
    }
    
    // Path/Filesクラス
    public static void modernPathClass() throws IOException {
        Path path = Paths.get("data.txt");
        
        // ファイルの存在確認
        System.out.println("存在するか:" + Files.exists(path));
        
        // ファイルのサイズ
        System.out.println("ファイルサイズ:" + Files.size(path) + " バイト");
        
        // 最終更新日時
        System.out.println("最終更新:" + Files.getLastModifiedTime(path));
        
        // ファイル属性の確認
        System.out.println("読み取り可能:" + Files.isReadable(path));
        System.out.println("書き込み可能:" + Files.isWritable(path));
        
        // ファイルのコピー
        Path copyPath = Paths.get("copy.txt");
        Files.copy(path, copyPath, StandardCopyOption.REPLACE_EXISTING);
        System.out.println("ファイルをコピーしました");
        
        // ファイルの削除
        Files.delete(path);
        System.out.println("ファイルを削除しました");
    }
    
    // ディレクトリ内のファイル一覧
    public static void listFiles(String directoryPath) throws IOException {
        Path dir = Paths.get(directoryPath);
        
        Files.list(dir)
            .forEach(path -> System.out.println(path.getFileName()));
    }
    
    public static void main(String[] args) throws IOException {
        // テストファイル作成
        Files.write(Paths.get("data.txt"), "テストデータ".getBytes());
        
        modernPathClass();
    }
}

2. 自分なりの解釈

  • ストリームの概念は、ファイルだけでなくネットワークやキーボード入力など、様々なデータソースに統一的にアクセスするための重要な仕組み。
  • try-with-resourcesの登場により、ファイルのクローズ漏れがなくなり、より安全で読みやすいコードが実現できるようになった。
  • Path/Filesクラスの導入により、ファイルシステム操作がより直感的で、複雑な操作も簡潔に記述できるようになった。

最後まで見ていただきありがとうございました。
次回は、第2部 / 第7章「さまざまなファイル形式」について書く予定です。


0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?