C#でバイナリファイルを読み書きする方法|FileStream・BinaryReaderの使い方をサンプルコードで解説
はじめに
C#でファイル操作を行う際、テキストファイルだけでなく、画像や音声、独自フォーマットのデータなどを扱うためにはバイナリファイルの読み書きが必要です。本記事では、C#におけるバイナリファイル操作の基本から応用まで、FileStreamやBinaryReader、BinaryWriterを使った具体的なサンプルコードを交えて解説します。初心者でも理解できるよう、ステップごとに丁寧に説明します。
1. C#で扱うバイナリファイルとは
1-1. バイナリファイルとテキストファイルの違い
バイナリファイルは文字コードではなく0と1の並びでデータを格納します。テキストファイルは文字として読み書きできるのに対し、バイナリファイルは数値や画像、音声など任意の形式のデータを効率よく保存できます。
1-2. バイナリファイルを読み書きする主な用途
画像・音声・動画ファイルの操作
独自フォーマットのデータ保存
高速な数値計算結果の格納
ネットワーク通信でのデータ送受信
1-3. C#でバイナリファイル操作に使う代表的なクラス
C#では主に以下のクラスを使用します。
FileStream:ファイルの読み書き全般を低レベルで操作BinaryReader:バイト単位や型ごとにデータを読み込むBinaryWriter:バイト単位や型ごとにデータを書き込む
1-4. FileStream・BinaryReader・BinaryWriterの役割の違い
FileStream:ストリームとしてファイルにアクセス
BinaryReader:FileStreamから型付きデータを安全に読み込む
BinaryWriter:FileStreamに型付きデータを書き込む
2. C#でバイナリファイルを読み書きする基本手順
2-1. System.IO名前空間を使用する
バイナリファイル操作はSystem.IO名前空間に含まれるクラスを使用します。
C#using System.IO;
2-2. FileStreamでファイルを開く
C#FileStream fs = new FileStream("sample.bin", FileMode.OpenOrCreate, FileAccess.ReadWrite);
2-3. BinaryReaderでデータを読み込む
C#using (BinaryReader reader = new BinaryReader(fs))
{
int number = reader.ReadInt32();
}
2-4. BinaryWriterでデータを書き込む
C#using (BinaryWriter writer = new BinaryWriter(fs))
{
writer.Write(1234);
}
2-5. using文でファイルを安全に閉じる
using文を使うと、ファイルが自動的に閉じられ、リソースリークを防げます。
3. FileStreamを使ってバイナリファイルを読み込む方法
3-1. FileStreamの基本構文
C#FileStream fs = new FileStream("file.bin", FileMode.Open, FileAccess.Read);
3-2. FileMode・FileAccess・FileShareの指定方法
FileMode.Open:既存ファイルを開くFileAccess.Read:読み取り専用FileShare.ReadWrite:他プロセスと共有
3-3. Readメソッドでbyte配列に読み込むサンプルコード
C#byte[] buffer = new byte[fs.Length];
fs.Read(buffer, 0, buffer.Length);
3-4. ファイルサイズを取得して全バイトを読み込む方法
C#long size = fs.Length;
byte[] data = new byte[size];
fs.Read(data, 0, data.Length);
3-5. 大きなバイナリファイルを分割して読み込む方法
C#byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = fs.Read(buffer, 0, buffer.Length)) > 0)
{
// 読み込んだデータを処理
}
4. BinaryReaderを使ってバイナリデータを読み込む方法
4-1. BinaryReaderの基本構文
C#using (BinaryReader reader = new BinaryReader(fs))
{
// 読み込み処理
}
4-2. ReadByte・ReadBytesでバイト単位に読み込む
C#byte singleByte = reader.ReadByte();
byte[] bytes = reader.ReadBytes(10);
4-3. ReadInt32・ReadDouble・ReadStringで型ごとに読み込む
C#int number = reader.ReadInt32();
double value = reader.ReadDouble();
string text = reader.ReadString();
4-4. 読み込み位置をSeekで移動する方法
C#reader.BaseStream.Seek(0, SeekOrigin.Begin); // ファイル先頭に戻す
4-5. EndOfStreamや例外を考慮した安全な読み込み方法
C#while (reader.BaseStream.Position < reader.BaseStream.Length)
{
int data = reader.ReadInt32();
}
5. BinaryWriterを使ってバイナリファイルに書き込む方法
5-1. BinaryWriterの基本構文
C#using (BinaryWriter writer = new BinaryWriter(fs))
{
writer.Write(100);
}
5-2. byte配列を書き込むサンプルコード
C#byte[] bytes = { 1, 2, 3, 4 };
writer.Write(bytes);
5-3. int・double・stringなど複数の型を書き込む方法
C#writer.Write(123);
writer.Write(3.14);
writer.Write("Hello");
5-4. 既存ファイルへ上書き・追記する方法
上書き:
FileMode.Create追記:
FileMode.Append
5-5. 書き込んだデータをBinaryReaderで読み戻して確認する方法
C#fs.Seek(0, SeekOrigin.Begin);
using (BinaryReader reader = new BinaryReader(fs))
{
int readValue = reader.ReadInt32();
}
6. FileStreamだけでバイナリファイルを読み書きする方法
6-1. FileStream.Writeでbyte配列を書き込む
C#byte[] data = { 10, 20, 30 };
fs.Write(data, 0, data.Length);
6-2. FileStream.Readでbyte配列を読み込む
C#byte[] buffer = new byte[fs.Length];
fs.Read(buffer, 0, buffer.Length);
6-3. BinaryReader・BinaryWriterを使う場合との違い
FileStream単体は型情報を扱えない
BinaryReader/Writerは型ごとの読み書きが可能
6-4. byte配列だけを扱う場合にFileStreamが向いている理由
型変換不要で直接操作できる
大容量データの高速処理に適している
7. C#でバイナリファイルを読み書きする実践サンプル
7-1. 数値データをバイナリファイルに保存するサンプル
C#int[] numbers = { 10, 20, 30 };
using (BinaryWriter writer = new BinaryWriter(File.Open("numbers.bin", FileMode.Create)))
{
foreach (var n in numbers)
writer.Write(n);
}
7-2. 保存した数値データを読み込むサンプル
C#using (BinaryReader reader = new BinaryReader(File.Open("numbers.bin", FileMode.Open)))
{
while (reader.BaseStream.Position < reader.BaseStream.Length)
Console.WriteLine(reader.ReadInt32());
}
7-3. 画像や任意ファイルをbyte配列としてコピーするサンプル
C#byte[] imageData = File.ReadAllBytes("image.png");
File.WriteAllBytes("copy.png", imageData);
7-4. 独自フォーマットのバイナリファイルを作成するサンプル
C#using (BinaryWriter writer = new BinaryWriter(File.Open("custom.bin", FileMode.Create)))
{
writer.Write("Header");
writer.Write(12345);
}
7-5. ヘッダー情報とデータ本体を分けて読み書きするサンプル
C#using (BinaryWriter writer = new BinaryWriter(File.Open("data.bin", FileMode.Create)))
{
writer.Write("HEADER"); // ヘッダー
writer.Write(new byte[] { 1, 2, 3, 4 }); // データ本体
}
8. バイナリファイル操作でよくあるエラーと対処法
8-1. ファイルが見つからない場合の対処
FileNotFoundExceptionをキャッチファイルパスを確認
8-2. ファイルが使用中で開けない場合の対処
FileShareオプションを確認他プロセスで開かれていないかチェック
8-3. 読み込みサイズが不足する場合の対処
BaseStream.Lengthでサイズを確認必要なバイト数を確保して読み込む
8-4. データ型や読み込み順を間違えた場合の対処
書き込み順と読み込み順を一致させる
型ごとに正しく読み込む
8-5. 文字列のエンコーディングに注意する
BinaryWriterはUTF-8で書き込む他のエンコーディングで読み込みたい場合は変換が必要
9. バイナリファイル操作の注意点とベストプラクティス
9-1. using文でリソース解放を徹底する
自動でファイルを閉じる
リソースリークを防ぐ
9-2. 読み込み順と書き込み順を一致させる
型ごとの順序を守る
読み込み時の例外を防ぐ
9-3. 大容量ファイルでは一括読み込みを避ける
分割読み込みでメモリ消費を抑える
ReadやReadBytesを活用
9-4. 例外処理でファイル破損やアクセス権限エラーに備える
try-catchで例外処理エラー時にバックアップを作る
9-5. バイナリデータの中身を確認するデバッグ方法
Hexエディタで直接確認デバッグ用にbyte配列を表示
10. C#のバイナリファイル操作でよくある質問
10-1. File.ReadAllBytesとの違いは何か
File.ReadAllBytesは一括読み込み専用大容量ファイルでは
FileStreamの方が効率的
10-2. BinaryReaderとFileStreamはどちらを使うべきか
型付きデータなら
BinaryReaderbyte単位の大量データなら
FileStream
10-3. バイナリファイルを構造体として読み込めるか
MarshalやBinaryFormatterで可能型のサイズと順序に注意
10-4. テキストファイルをバイナリとして読み込めるか
可能だが、文字コードに注意
UTF-8などで文字化けする場合あり
10-5. .NET Frameworkと.NETで書き方は違うか
基本は同じ
新しい.NETでは
FileStreamやBinaryReaderの拡張機能あり
まとめ
C#でのバイナリファイル操作は、FileStreamを基盤としてBinaryReader・BinaryWriterを組み合わせることで、安全かつ効率的に実現できます。型ごとの読み書きやファイル分割、大容量データの扱い方を理解すれば、画像や独自フォーマットのデータも自在に操作可能です。using文や例外処理を徹底することで、ファイル破損やメモリリークを防ぎながら、堅牢なプログラムを作ることができます。

