ファイルIO

ファイル操作はプログラムの重要な機能です。このレッスンでは、JavaのファイルIOを学びます。

Fileクラス

Fileクラスはファイルやディレクトリを操作するために使用されます。

Fileオブジェクトの作成

JAVA
import java.io.File;

// 方法1:パス文字列
File file1 = new File("test.txt");

// 方法2:親パス + ファイル名
File file2 = new File("/home/user", "test.txt");

// 方法3:Fileオブジェクト + ファイル名
File dir = new File("/home/user");
File file3 = new File(dir, "test.txt");

一般的なメソッド

メソッド 説明
exists() 存在するか
isFile() ファイルか
isDirectory() ディレクトリか
getName() ファイル名を取得
getPath() パスを取得
getAbsolutePath() 絶対パスを取得
length() ファイルサイズ(バイト)
createNewFile() ファイルを作成
mkdir() ディレクトリを作成
mkdirs() ネストされたディレクトリを作成
delete() 削除
list() ディレクトリの内容を一覧表示

例:ファイル操作

JAVA
import java.io.File;
import java.io.IOException;

public class FileDemo {
    public static void main(String[] args) throws IOException {
        File file = new File("test.txt");
        
        // ファイルを作成
        if (!file.exists()) {
            file.createNewFile();
            System.out.println("ファイルが正常に作成されました");
        }
        
        // ファイル情報
        System.out.println("ファイル名: " + file.getName());
        System.out.println("パス: " + file.getPath());
        System.out.println("絶対パス: " + file.getAbsolutePath());
        System.out.println("サイズ: " + file.length() + " バイト");
        System.out.println("ファイルか: " + file.isFile());
        System.out.println("ディレクトリか: " + file.isDirectory());
        
        // ファイルを削除
        // file.delete();
    }
}
▶ 試してみよう

例:ディレクトリ操作

JAVA
import java.io.File;

public class DirectoryDemo {
    public static void main(String[] args) {
        // ディレクトリを作成
        File dir = new File("testdir/subdir");
        dir.mkdirs();
        System.out.println("ディレクトリが作成されました: " + dir.getAbsolutePath());
        
        // ディレクトリの内容を一覧表示
        File parent = new File("testdir");
        String[] files = parent.list();
        if (files != null) {
            for (String name : files) {
                System.out.println("  " + name);
            }
        }
        
        // ディレクトリを走査
        File[] fileArray = parent.listFiles();
        if (fileArray != null) {
            for (File f : fileArray) {
                String type = f.isDirectory() ? "[DIR]" : "[FILE]";
                System.out.println(type + " " + f.getName());
            }
        }
    }
}
▶ 試してみよう

ファイル読み書き

BufferedReaderによるファイル読み取り

JAVA
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class ReadFile {
    public static void main(String[] args) {
        // try-with-resourcesでリソースを自動閉じる
        try (BufferedReader reader = new BufferedReader(new FileReader("test.txt"))) {
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            System.out.println("読み取り失敗: " + e.getMessage());
        }
    }
}

BufferedWriterによるファイル書き込み

JAVA
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

public class WriteFile {
    public static void main(String[] args) {
        // 上書き
        try (BufferedWriter writer = new BufferedWriter(new FileWriter("output.txt"))) {
            writer.write("Hello, World!");
            writer.newLine();
            writer.write("Javaファイル操作");
            System.out.println("書き込み成功");
        } catch (IOException e) {
            System.out.println("書き込み失敗: " + e.getMessage());
        }
        
        // 追記
        try (BufferedWriter writer = new BufferedWriter(new FileWriter("output.txt", true))) {
            writer.write("追加コンテンツ");
            writer.newLine();
            System.out.println("追加成功");
        } catch (IOException e) {
            System.out.println("追加失敗: " + e.getMessage());
        }
    }
}

try-with-resources

Java 7で導入され、AutoCloseableを実装したリソースを自動的に閉じます。

構文

JAVA
try (リソース型 変数 = new リソース()) {
    // リソースを使用
} catch (例外型 e) {
    // 例外を処理
}

例:ファイルコピー

JAVA
import java.io.*;

public class FileCopy {
    public static void copy(String src, String dest) throws IOException {
        try (BufferedReader reader = new BufferedReader(new FileReader(src));
             BufferedWriter writer = new BufferedWriter(new FileWriter(dest))) {
            
            String line;
            while ((line = reader.readLine()) != null) {
                writer.write(line);
                writer.newLine();
            }
        }
        System.out.println("コピー完了");
    }
    
    public static void main(String[] args) {
        try {
            copy("source.txt", "dest.txt");
        } catch (IOException e) {
            System.out.println("コピー失敗: " + e.getMessage());
        }
    }
}
▶ 試してみよう

すべての内容を読み取る

方法1:行ごとに読み取る

JAVA
public static String readAll(String filename) throws IOException {
    StringBuilder sb = new StringBuilder();
    try (BufferedReader reader = new BufferedReader(new FileReader(filename))) {
        String line;
        while ((line = reader.readLine()) != null) {
            sb.append(line).append("\n");
        }
    }
    return sb.toString();
}

方法2:Filesユーティリティクラス(Java 7+)

JAVA
import java.nio.file.Files;
import java.nio.file.Paths;
import java.io.IOException;
import java.util.List;

public class FilesDemo {
    public static void main(String[] args) throws IOException {
        // すべての行を読み取る
        List<String> lines = Files.readAllLines(Paths.get("test.txt"));
        lines.forEach(System.out::println);
        
        // 文字列として読み取る
        String content = new String(Files.readAllBytes(Paths.get("test.txt")));
        System.out.println(content);
        
        // ファイルに書き込む
        Files.write(Paths.get("output.txt"), "Hello".getBytes());
    }
}

ファイル走査

再帰的なディレクトリ一覧

JAVA
import java.io.File;

public class ListFiles {
    public static void listFiles(File dir, String indent) {
        File[] files = dir.listFiles();
        if (files == null) return;
        
        for (File file : files) {
            System.out.println(indent + file.getName());
            if (file.isDirectory()) {
                listFiles(file, indent + "  ");
            }
        }
    }
    
    public static void main(String[] args) {
        File dir = new File(".");
        listFiles(dir, "");
    }
}

ファイルフィルタリング

JAVA
import java.io.File;
import java.io.FilenameFilter;

public class FileFilter {
    public static void main(String[] args) {
        File dir = new File(".");
        
        // .txtファイルのみ一覧表示
        String[] txtFiles = dir.list((d, name) -> name.endsWith(".txt"));
        if (txtFiles != null) {
            for (String name : txtFiles) {
                System.out.println(name);
            }
        }
        
        // ディレクトリのみ一覧表示
        File[] dirs = dir.listFiles(File::isDirectory);
        if (dirs != null) {
            for (File d : dirs) {
                System.out.println("[DIR] " + d.getName());
            }
        }
    }
}

シリアライゼーション

オブジェクトをバイトストリームに変換し、ファイルへの保存やネットワーク送信を可能にします。

シリアライゼーションの要件

例:シリアライゼーション

JAVA
import java.io.*;

// シリアライズ可能なクラス
public class User implements Serializable {
    private static final long serialVersionUID = 1L;
    private String name;
    private int age;
    private transient String password;  // transientはシリアライゼーションから除外
    
    public User(String name, int age, String password) {
        this.name = name;
        this.age = age;
        this.password = password;
    }
    
    @Override
    public String toString() {
        return "User{name='" + name + "', age=" + age + ", password='" + password + "'}";
    }
}

public class SerializeDemo {
    public static void main(String[] args) {
        // シリアライズ
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("user.dat"))) {
            User user = new User("Alice", 25, "123456");
            oos.writeObject(user);
            System.out.println("シリアライズ成功");
        } catch (IOException e) {
            System.out.println("シリアライズ失敗: " + e.getMessage());
        }
        
        // デシリアライズ
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user.dat"))) {
            User user = (User) ois.readObject();
            System.out.println("デシリアライズ: " + user);
            // User{name='Alice', age=25, password='null'}(パスワードは除外)
        } catch (IOException | ClassNotFoundException e) {
            System.out.println("デシリアライズ失敗: " + e.getMessage());
        }
    }
}
▶ 試してみよう

❓ よくある質問

Q 相対パスと絶対パスの違いは何ですか?
A 相対パスは現在の作業ディレクトリからの相対パスです。絶対パスはルートディレクトリから始まります。
Q なぜtry-with-resourcesを使用するのですか?
A リソースを自動的に閉じ、リソースリークを防止します。手動のfinallyより簡潔です。
Q transientキーワードは何をしますか?
A シリアライゼーションに参加すべきでないフィールドをマークします。

📖 まとめ

📝 演習

  1. ファイル統計: ファイル内の行数、単語数、文字数をカウント
  2. ファイルコピー: 大きなファイルをサポートするファイルコピーを実装
  3. ディレクトリ走査: ディレクトリ内のすべてのファイルを再帰的に一覧表示し、サイズでソート

次のレッスン

次のレッスンでは、ストリームとNIOを学びます — JavaのストリームベースIO。

100%