CodeGym /コース /C# SELF /ファイルフォーマット: テキストとバイナリ

ファイルフォーマット: テキストとバイナリ

C# SELF
レベル 35 , レッスン 1
使用可能

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
books.txt(CSVフォーマット)の中身例

各行が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 だよ。)

同じ数字をテキストとバイナリで保存して、ファイルサイズを比べてみて。バイナリの方がちょっと小さいはず。

プログラムがバイナリファイルを扱う方法

専用のストリーム(BinaryReaderBinaryWriterなど)を使う。テキストファイルと違って、構造をちゃんと知ってないとデータを読めない。


// 数字をバイナリファイルに書く例
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. フォーマット操作でよくあるミス

バイナリファイルをテキストとして読もうとすると、文字化けやエラーになる。逆に、テキストファイルをバイナリとして開いて、厳密な構造を期待してもダメ。

一番ありがちなのは、データ構造と読み書きの順番がズレること。例えば、最初に年を書いてからタイトルを書いたのに、読むときは逆にしたら、全然違うデータになる。必ず同じ順番で操作しよう!

プログラマーはよくテキストファイルを「覗き見」して、保存や読み込みロジックをチェックする。だから最初はテキストフォーマットが便利。バイナリは、もっと高度な用途や、ユーザーに中身を見せたくないときに使うのがオススメ。

コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION