JavaのI/Oストリーム入門

I/Oストリーム

データの保存と読み取りのためのソリューションです。ローカルファイルやネットワーク上のデータの読み書きに使用されます。

分類:

  1. 方向による分類:
    1. 入力ストリーム
    2. 出力ストリーム
  2. 操作するファイルタイプによる分類:
    1. バイトストリーム
    2. 文字ストリーム

FileOutputStream

ファイルへのデータ書き込みに使用されるクラスです。

基本的な使用例:


public static void main(String[] args) throws IOException {
    FileOutputStream fos = new FileOutputStream("data\\output.txt");
    fos.write(97); // 'a'を書き込む
    fos.close();
}

コンストラクタの詳細:

  • パラメータは文字列のパスまたはFileオブジェクトを使用できます
  • ファイルが存在しない場合は新しいファイルが作成されますが、親ディレクトリは存在している必要があります
  • ファイルが存在する場合はファイルがクリアされます

writeメソッドのバリエーション:


// 1バイト書き込む
void write(int b)

// バイト配列全体を書き込む
void write(byte[] b) 

// バイト配列の一部を書き込む
void write(byte[] b, int off, int len)

改行の書き込み:


// 改行文字の書き込み
// Windows: \r\n
// Linux: \n
// Mac: \r

String content = "これはテストです";
byte[] contentBytes = content.getBytes();
fos.write(contentBytes);

String newLine = "\r\n";
byte[] newLineBytes = newLine.getBytes();
fos.write(newLineBytes);

追記モード:


// 第二引数をtrueに設定すると追記モードになる
FileOutputStream fos = new FileOutputStream("data\\output.txt", true);

FileInputStream

ファイルからのデータ読み取りに使用されるクラスです。

基本的な使用例:


FileInputStream fis = new FileInputStream("data\\input.txt");

int data = fis.read();
// ファイルの終わりに達すると-1を返す

fis.close();

ループを使用した読み取り:


FileInputStream fis = new FileInputStream("data\\input.txt");
int byteData;
while((byteData = fis.read()) != -1) {
    System.out.println((char)byteData);
}
fis.close();

ファイルのコピー

基本的なコピー方法:


// 元ファイルから読み取り、先ファイルに書き込む
FileInputStream fis = new FileInputStream("source\\file.mp4");
FileOutputStream fos = new FileOutputStream("destination\\copy.mp4");

int byteData;
while((byteData = fis.read()) != -1) {
    fos.write(byteData);
}

// リソースの解放(後から開いたものから閉じる)
fos.close();
fis.close();

効率的なコピー方法:


// バッファを使用した効率的なコピー
FileInputStream fis = new FileInputStream("source\\largefile.mp4");
FileOutputStream fos = new FileOutputStream("destination\\copy.mp4");

byte[] buffer = new byte[1024 * 1024 * 5]; // 5MBのバッファ
int bytesRead;
while((bytesRead = fis.read(buffer)) != -1) {
    fos.write(buffer, 0, bytesRead);
}

fos.close();
fis.close();

例外処理

try-catch-finally構文:


try {
    // ファイル操作のコード
} catch (IOException e) {
    // 例外処理
} finally {
    // リソースの解放
}

try-with-resources構文(JDK9以降):


try (FileInputStream fis = new FileInputStream("source\\file.mp4");
     FileOutputStream fos = new FileOutputStream("destination\\copy.mp4")) {
     
    byte[] buffer = new byte[1024];
    int bytesRead;
    while((bytesRead = fis.read(buffer)) != -1) {
        fos.write(buffer, 0, bytesRead);
    }
} catch (IOException e) {
    e.printStackTrace();
}

文字ストリーム

文字セットとエンコーディングに関する重要な概念:

  • GB2312/GBK文字セット(Windowsでデフォルト使用)
  • Unicode文字セット(万国語コード)
  • UTF-8エンコーディング(1〜4バイトを使用)

文字化けの問題:

  • 原因1: 漢字全体を読み取る前に読み取りが終了する
  • 原因2: エンコードとデコードで異なる文字セットを使用する

FileReaderの使用例:


// 文字ファイルの読み取り
FileReader fr = new FileReader("data\\text.txt");

int charData;
while((charData = fr.read()) != -1) {
    System.out.print((char)charData);
}

fr.close();

FileWriterの使用例:


// 文字ファイルへの書き込み
FileWriter fw = new FileWriter("data\\output.txt");

// 文字の書き込み
fw.write('あ');

// 文字列の書き込み
fw.write("こんにちは世界");

// 配列の書き込み
char[] charArray = {'H', 'e', 'l', 'l', 'o'};
fw.write(charArray);

// 追記モード
FileWriter fwAppend = new FileWriter("data\\output.txt", true);

fw.close();
fwAppend.close();

バッファリングされたストリーム

バッファ付きバイトストリーム:


// バッファ付き入力ストリーム
BufferedInputStream bis = new BufferedInputStream(
    new FileInputStream("data\\input.txt"));

// バッファ付き出力ストリーム
BufferedOutputStream bos = new BufferedOutputStream(
    new FileOutputStream("data\\output.txt"));

// データの読み書き
int byteData;
while((byteData = bis.read()) != -1) {
    bos.write(byteData);
}

bos.close();
bis.close();

バッファ付き文字ストリーム:


// バッファ付き文字入力ストリーム
BufferedReader br = new BufferedReader(
    new FileReader("data\\text.txt"));

// 1行ずつ読み取り
String line;
while((line = br.readLine()) != null) {
    System.out.println(line);
}

br.close();

バッファ付き文字出力ストリーム:


// バッファ付き文字出力ストリーム
BufferedWriter bw = new BufferedWriter(
    new FileWriter("data\\output.txt", true));

// データの書き込み
bw.write("これは最初の行です");
bw.newLine(); // クロスプラットフォームの改行
bw.write("これは2行目です");

bw.close();

変換ストリーム

バイトストリームと文字ストリーム間の橋渡し役です。

指定された文字セットでの読み取り:


// 指定された文字セットでファイルを読み取る
FileReader fr = new FileReader("data\\gbkfile.txt", 
    Charset.forName("GBK"));

int charData;
while((charData = fr.read()) != -1) {
    System.out.print((char)charData);
}

fr.close();

指定された文字セットでの書き込み:


// 指定された文字セットでファイルに書き込む
FileWriter fw = new FileWriter("data\\output.txt", 
    Charset.forName("UTF-8"));

fw.write("これはUTF-8で書き込まれたテキストです");
fw.close();

直列化ストリーム

Javaオブジェクトをファイルに保存(シリアライズ)し、後で読み取る(デシリアライズ)ためのストリームです。

シリアライズ:


// Serializableインターフェースを実装したクラス
class Student implements Serializable {
    private static final long serialVersionUID = 1L;
    private String name;
    private int age;
    
    // コンストラクタ、ゲッター、セッター
}

// オブジェクトのシリアライズ
Student student = new Student("Taro", 20);

ObjectOutputStream oos = new ObjectOutputStream(
    new FileOutputStream("data\\student.ser"));

oos.writeObject(student);
oos.close();

デシリアライズ:


// オブジェクトのデシリアライズ
ObjectInputStream ois = new ObjectInputStream(
    new FileInputStream("data\\student.ser"));

Student deserializedStudent = (Student) ois.readObject();
System.out.println(deserializedStudent.getName());

ois.close();

印刷ストリーム

データをそのまま書き込み、自動フラッシュと自動改行を提供します。

バイト印刷ストリーム:


PrintStream ps = new PrintStream(
    new FileOutputStream("data\\output.txt"), true, "UTF-8");

ps.println(97); // 自動改行
ps.print(true); // 改行なし
ps.printf("%sは%sが好きです", "私", "Java");

ps.close();

文字印刷ストリーム:


PrintWriter pw = new PrintWriter(
    new FileWriter("data\\output.txt"), true);

pw.println("これは印刷ストリームのテストです");
pw.print("改行なしのテキスト");

pw.close();

圧縮・解凍ストリーム

ZIPファイルの解凍:


// ZIPファイルの解凍
File zipFile = new File("data\\archive.zip");
File destDir = new File("data\\extracted");

try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile))) {
    ZipEntry entry;
    while ((entry = zis.getNextEntry()) != null) {
        File file = new File(destDir, entry.getName());
        if (entry.isDirectory()) {
            file.mkdirs();
        } else {
            new File(file.getParent()).mkdirs();
            try (FileOutputStream fos = new FileOutputStream(file)) {
                byte[] buffer = new byte[1024];
                int len;
                while ((len = zis.read(buffer)) > 0) {
                    fos.write(buffer, 0, len);
                }
            }
        }
        zis.closeEntry();
    }
}

ZIPファイルの作成:


// ZIPファイルの作成
File sourceDir = new File("data\\to_compress");
File zipFile = new File("data\\compressed.zip");

try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFile))) {
    addDirToZip(sourceDir, sourceDir.getName(), zos);
}

// ディレクトリをZIPに追加するヘルパーメソッド
private static void addDirToZip(File dir, String basePath, 
    ZipOutputStream zos) throws IOException {
    File[] files = dir.listFiles();
    if (files != null) {
        for (File file : files) {
            if (file.isDirectory()) {
                addDirToZip(file, basePath + "/" + file.getName(), zos);
            } else {
                ZipEntry entry = new ZipEntry(basePath + "/" + file.getName());
                zos.putNextEntry(entry);
                try (FileInputStream fis = new FileInputStream(file)) {
                    byte[] buffer = new byte[1024];
                    int len;
                    while ((len = fis.read(buffer)) > 0) {
                        zos.write(buffer, 0, len);
                    }
                }
                zos.closeEntry();
            }
        }
    }
}

便利なライブラリ

Apache Commons IO:


// ファイルのコピー
File source = new File("data\\source.txt");
File dest = new File("data\\destination.txt");
FileUtils.copyFile(source, dest);

// ディレクトリのコピー
File sourceDir = new File("data\\source_dir");
File destDir = new File("data\\dest_dir");
FileUtils.copyDirectoryToDirectory(sourceDir, destDir);

// ファイルの内容を文字列として読み取る
File file = new File("data\\text.txt");
String content = FileUtils.readFileToString(file, StandardCharsets.UTF_8);

// 文字列をファイルに書き込む
String text = "これは書き込むテキストです";
FileUtils.write(new File("data\\output.txt"), text, StandardCharsets.UTF_8);

Hutool:

HutoolはJava開発のためのオープンソースツールキットで、IO操作を簡素化します。


// ファイルのコピー
FileUtil.copy(new File("data\\source.txt"), new File("data\\dest.txt"), true);

// ディレクトリのコピー
FileUtil.copy(new File("data\\source_dir"), new File("data\\dest_dir"), true);

// ファイルの読み込み
String content = FileUtil.readUtf8String("data\\text.txt");

// ファイルへの書き込み
FileUtil.writeUtf8String("書き込むテキスト", "data\\output.txt");

タグ: Java I/Oストリーム ファイル操作 シリアライズ バッファリング

7月1日 21:44 投稿