I/Oストリーム
データの保存と読み取りのためのソリューションです。ローカルファイルやネットワーク上のデータの読み書きに使用されます。
分類:
- 方向による分類:
- 入力ストリーム
- 出力ストリーム
- 操作するファイルタイプによる分類:
- バイトストリーム
- 文字ストリーム
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");