1. テキストファイル
思い出してみて:コンピュータはすべて、ほんとに全部、1と0(もしくは、怖くなければ「バイト列」って言葉でもOK)で保存してる。でも、同じファイルを2つのプログラムに食わせても、同じように反応するとは限らない。例えば、あるプログラムは普通のテキストとして見るけど、別のは「壊れたバイトの集まり」としか見えないことも。全部はファイルフォーマット、つまりバイトをどう解釈するかにかかってる。フォーマットはデータの内部構造、読み方、エンコーディングのルールを決めてる。フォーマットを知らないと、プログラムはファイルの中身を理解できないんだ。
テキストファイルは、データが普通のテキスト(たいていUTF-8、ガチ勢ならASCII)で保存されてるファイルのこと。こういうファイルはどんなテキストエディタ(NotepadとかVS Codeとか)でも開けて、すぐ読める。中身は文字列で、謎の制御バイトやバイナリ構造じゃないよ。
よくある例
- *.txt — 普通のテキストファイル、例えば "to-do.txt" や "best-books.txt"。
- *.csv — データがカンマやセミコロンで区切られてるファイル(表データに便利)。
- *.json — 構造化データのやりとり用ファイル(例:本のリスト)。
- *.xml,*.html — 構造化データの保存や転送用。
CSVファイルの例
デューン;フランク・ハーバート;1965
1984;ジョージ・オーウェル;1949
巨匠とマルガリータ;ミハイル・ブルガーコフ;1966
各行が1つのレコード(例えば本)になってる。行の中の値はセミコロンで区切られてて、これがCSV(Comma-Separated Values)の例。Commaってカンマだけど、ここでは別の区切り文字(;)を使ってる。人間が見てる文字も、プログラムが読むバイトも同じだけど、プログラムがテキストフォーマットとエンコーディングを知ってる前提ね。
プログラムがテキストファイルを扱う方法
ファイルを「テキスト」として開けば、1行ずつ読める。例(今後のレクチャーで役立つよ):
// ファイルから行を読むだけ(詳細はまた今度!)
string[] lines = File.ReadAllLines("books.txt");
foreach (string line in lines)
{
Console.WriteLine(line);
}
テキストファイルのメリット
- 人間が読める(human-readable)。
- 手動で簡単に編集できる(NotepadみたいなアプリでもOK)。
- デバッグや異なるシステム間のやりとりに最適。
- いろんなプラットフォーム(Windows, Linux, Mac)間で簡単に移動できる。
テキストファイルのデメリット
- 厳密な構造がない(txt)、フォーマットミスが起きやすい。
- 容量が大きくなりがち(例:12345 は5バイト、バイナリなら4バイト)。
- 複雑なデータ(画像や音声など)はテキストで扱いにくい、または無理。
- 大量データだとパフォーマンスが悪い。
知っておくと便利
- プラットフォームごとに「改行」の扱いが違う:Windowsは \r\n、Unixは \n。
- エンコーディングも色々(UTF-8, UTF-16, ANSIなど)。だから、あるシステムで書いたファイルが別のシステムで「中国語みたいな文字」になることも(実はバイトの解釈ミス)。
2. バイナリファイル
バイナリファイルは、文字じゃなくて好きなバイトが入ってるファイル。数字、構造体、画像、音楽、マシンコード…なんでもアリ。.exeをメモ帳で開いてみると、意味不明な文字の嵐が見えるはず!
よくある例
- *.exe, *.dll — 実行ファイルやライブラリ。
- *.jpg, *.png, *.gif— 画像ファイル。
- *.mp3, *.wav— 音声ファイル。
- *.dat — 任意のユーザーデータ。
- アプリ専用フォーマット(*.docx, *.xlsxなど)— ほぼ全部バイナリ。
バイナリファイルの中身って?
プログラムはバイト単位で、必要なフォーマットでデータを書いたり読んだりする。例えば、int型の数字は4バイト(32ビット)で保存されるし、文字列は「長さ+バイト列(エンコーディング付き)」みたいな感じ。
テキストファイルで12345って数字は、'1','2','3','4','5'の文字に対応するバイトになる:
| 文字 | UTF-8コード |
|---|---|
| 1 | 49 |
| 2 | 50 |
| 3 | 51 |
| 4 | 52 |
| 5 | 53 |
バイナリファイルだと、int 12345(リトルエンディアン)はこうなる:
| 位置 | バイト (hex) | 値 |
|---|---|---|
| 0 | 0x39 | 57 |
| 1 | 0x30 | 48 |
| 2 | 0x00 | 0 |
| 3 | 0x00 | 0 |
(つまり:12345 = 0x00003039 だよ。)
同じ数字をテキストとバイナリで保存して、ファイルサイズを比べてみて。バイナリの方がちょっと小さいはず。
プログラムがバイナリファイルを扱う方法
専用のストリーム(BinaryReaderやBinaryWriterなど)を使う。テキストファイルと違って、構造をちゃんと知ってないとデータを読めない。
// 数字をバイナリファイルに書く例
var writer = new BinaryWriter(File.Open("books.bin", FileMode.Create));
// 例えば、エンコーディング:文字数(int)、その後バイト列
string title = "デューン";
writer.Write(title.Length); // 長さ(int)を書き込む
writer.Write(title); // 文字列を書き込む(UTF-8になる)
writer.Write(1965); // 年(int)を書き込む
writer.Close(); // ストリームを閉じる
これは単なる例。バイナリファイルの扱いは、また今度詳しくやるよ。
バイナリファイルのメリット
- コンパクト:容量が小さい。
- 読み書きが速い(特に大量データの場合)。
- 配列やネストしたオブジェクトなど、複雑な構造も保存できる。
バイナリファイルのデメリット
- 人間には読めない(human-unreadable)。
- ファイル構造が変わると、古いデータが壊れたり読めなくなる。
- 中身を解析するには、正確な手順が必須。
3. どっちのフォーマットを選ぶ?
テキスト vs バイナリファイル
| 基準 | テキストファイル | バイナリファイル |
|---|---|---|
| 人間が読める | はい | いいえ |
| サイズ | 大きい | 小さい |
| 汎用性 | 高い(どのエディタでも) | 専用プログラムのみ |
| 速度 | 遅い | 速い |
| フォーマットの厳密さ | なし | 必須 |
| 構造の保存 | 難しい | 簡単 |
| データ破損リスク | 低い(編集しやすい) | 高い(ちょっと壊れると読めない) |
選ぶ基準
- 人間が読めて、簡単に編集・デバッグしたい? — テキストファイルを使おう(例:.txt, .csv, .json)。
- データが複雑で、サイズや速度が大事? — バイナリフォーマット。
- 異なるプラットフォーム間でデータをやりとりしたい? — テキストがオススメだけど、エンコーディングは標準(UTF-8)で。
- アプリが大量データを読み書きして、フォーマットも厳密? — バイナリを選ぼう。
うちのコンソールアプリ「本リスト」の最初のうちは、テキストフォーマット(.csvや.txt)がベスト。あとで構造が複雑になったり、読み込み速度を上げたくなったら、バイナリやJSON/XMLにチャレンジしてみて。
4. ちょっとした豆知識
テキストとバイナリファイル、どこで使われてる?
テキストファイル:
- アプリの設定(.iniや.jsonが多い)。
- スクリプト、ログ、メモ。
- インポート/エクスポート用ファイル(アプリ間データ交換)。
バイナリファイル:
- プログラム、ゲーム、ライブラリ(普通は中身を見ない)。
- 大きなデータベースやアーカイブ(例:.mdb, .zip)。
- メディア:音楽、写真、動画。
ファイル全体を一気に読む(テキストの場合):
string allText = File.ReadAllText("books.txt");
// allTextにはファイルの全内容が入るよ
1行ずつ読む(リスト向き):
string[] lines = File.ReadAllLines("books.txt");
foreach (string line in lines)
{
// 行を分割できる
string[] parts = line.Split(';');
// parts[0] — タイトル, parts[1] — 著者, parts[2] — 年
}
バイナリ読み込み — 構造通りに!
var reader = new BinaryReader(File.Open("books.bin", FileMode.Open));
int count = reader.ReadInt32(); // 本の数
for (int i = 0; i < count; i++)
{
string title = reader.ReadString();
string author = reader.ReadString();
int year = reader.ReadInt32();
// これでレコードを復元できる!
}
reader.Close();
5. 実践例:本リストファイルを作ってみよう
データをテキストファイルに保存
各本を1行で保存するよ:
タイトル;著者;初版年
// 保存したい本リスト
var books = new List<(string Title, string Author, int Year)>
{
("デューン", "フランク・ハーバート", 1965),
("1984", "ジョージ・オーウェル", 1949),
("巨匠とマルガリータ", "ミハイル・ブルガーコフ", 1966)
};
// テキストファイルに保存
var writer = new StreamWriter("books.txt");
foreach (var book in books)
writer.WriteLine($"{book.Title};{book.Author};{book.Year}");
writer.Close();
books.txtをメモ帳で開けば、全部のデータが見えるよ。
データをバイナリファイルに保存
今度は同じデータを、もっとコンパクトに(でも人間には読めない)保存してみよう:
var writer = new BinaryWriter(File.Open("books.bin", FileMode.Create));
writer.Write(books.Count); // 本の数を書き込む
foreach (var book in books)
{
writer.Write(book.Title); // 文字列(長さ+バイト列で保存)
writer.Write(book.Author); // 文字列
writer.Write(book.Year); // 年(int)
}
writer.Close();
books.binをテキストエディタで開くと、意味不明な文字のカオスになる。これが普通。バイナリファイルは人間向けじゃなくて、「どうやって書いたか」を知ってるプログラムだけが正しく扱えるんだ。
6. フォーマット操作でよくあるミス
バイナリファイルをテキストとして読もうとすると、文字化けやエラーになる。逆に、テキストファイルをバイナリとして開いて、厳密な構造を期待してもダメ。
一番ありがちなのは、データ構造と読み書きの順番がズレること。例えば、最初に年を書いてからタイトルを書いたのに、読むときは逆にしたら、全然違うデータになる。必ず同じ順番で操作しよう!
プログラマーはよくテキストファイルを「覗き見」して、保存や読み込みロジックをチェックする。だから最初はテキストフォーマットが便利。バイナリは、もっと高度な用途や、ユーザーに中身を見せたくないときに使うのがオススメ。
GO TO FULL VERSION