1. Fileクラス:シンプル&効率的
System.IO.Fileクラスは「1操作=1メソッド」って感じのコンセプトを体現してる。OSとのややこしいやりとりを隠してくれる高レベルなメソッドが揃ってて、自分のやりたいことに集中できるんだ。
Fileクラスで何ができるの?
- テキストや任意のバイナリデータをファイルに書き込む。
- ファイルの内容を読む(全部一気に、または1行ずつ/テキストファイルの場合)。
- 既存ファイルのコピー、削除、リネーム。
- 指定パスのファイル存在チェック。
- ファイル属性の操作(例えば作成日やサイズは関連クラス経由で)。
なんで便利なの?
Fileのメソッドは全部static。つまり、オブジェクト作らなくても、必要なメソッドを呼ぶだけでOK。例えば:
File.WriteAllText("data.txt", "やあ、ファイル!");
このスタイル、Consoleクラスとそっくり:超シンプルで分かりやすいし、「何かを作る」必要も、ストリームのことも気にしなくていい。
ファイル操作の万能ツールが欲しいなら、System.IO.Fileクラスがまさにそれ。読み書き・コピー・削除など、基本的なファイル操作が全部揃ってて、まるでファイルシステム用のスイスアーミーナイフだよ。
Fileの使い方は?
Fileクラスのメソッドは全部staticだから、オブジェクト作らずにFile.なんとか()って書くだけ。Console.WriteLine()みたいな感じで、今度はファイル用ってわけ。
string text = "やあ、世界!";
string path = "hello.txt";
// テキストをファイルに書き込む(既存なら上書き!)
File.WriteAllText(path, text);
// ファイル全体を1つの文字列として読む
string readText = File.ReadAllText(path);
Console.WriteLine("ファイルの内容: " + readText);
ライフハック:もしReadAllTextやWriteAllTextを10回も連続で使ってたら、たぶんやり方間違ってるかも—これらはシンプルなシナリオや小さいファイル向けだよ。
Fileクラスのよく使うメソッド
| メソッド | 説明 |
|---|---|
|
指定パスのファイルが存在するかチェック |
|
ファイルを削除 |
|
ファイルをコピー |
|
ファイルを移動(またはリネーム) |
|
ファイル全体を1つの文字列として読む |
|
文字列をファイルに書き込む(既存なら上書き) |
|
ファイルの全行を文字列配列で読む |
|
文字列配列をファイルに書き込む(各行ごと) |
|
ファイルの全バイトをバイト配列で読む |
|
バイト配列をファイルに書き込む |
2. テキストファイルの書き込みと読み込み
Fileクラスのよく使うメソッドを実例で見てみよう。使うには、コードファイルの先頭にusing System.IO;が必要だよ。
using System;
using System.IO; // Fileクラス使うなら必須
using System.Linq; // ReadLinesで必要な場合あり
ファイル全体を読む
よくあるタスクの一つ:テキストデータをファイルに保存したり、逆に読み込んだり。
1行(または全テキスト)を書き込む:File.WriteAllText() このメソッドは指定パスに新しいファイルを作る。同じ名前のファイルが既にあれば、内容は新しいテキストで完全に上書きされる。
string myFilePath = "notes.txt";
string textContent = "今日はC#を学ぶのに最高の日。\n宿題も忘れずにね。";
// 全テキストをファイルに書き込む
File.WriteAllText(myFilePath, textContent);
Console.WriteLine($"ファイル '{myFilePath}' を作成/上書きしたよ。");
ファイル全体を1つの文字列として読む:File.ReadAllText() このメソッドはテキストファイルの内容を最初から最後まで全部読み込んで、1つの大きな文字列で返す。
string myFilePath = "notes.txt";
// 読み込む前にファイルの存在を必ずチェックしよう!
if (File.Exists(myFilePath))
{
string content = File.ReadAllText(myFilePath);
Console.WriteLine($"ファイル '{myFilePath}' の内容:\n{content}");
}
else
{
Console.WriteLine($"エラー: ファイル '{myFilePath}' が見つからないよ。");
}
重要な注意:File.WriteAllText()やFile.ReadAllText()は小〜中サイズのファイル(メモ、設定ファイル、短いログなど)に最適。でも、ファイルがめっちゃ大きい(数十〜数百MB、ましてやGB単位)と、全部を一気にメモリに読み込むのはメモリ大量消費やOutOfMemoryExceptionの原因になる。そういう時はもっと効率的な方法がある(後述&次回レクチャーで)。
3. ファイルを1行ずつ読む
でっかいテキストファイル(CSVレポートや長いログ、テキストDBなど)を扱う時、全部を一気にメモリに読み込むのは非効率だし、無理な場合もある。そんな時はFile.ReadLines()の出番!
File.ReadLines(path)はファイル全体を一度に読み込まない。代わりに、IEnumerable<string>っていうコレクションを返して、必要な時に1行ずつ読める。これを「遅延読み込み」または「ストリーム読み込み」って呼ぶよ。
string logFilePath = "application.log";
string text = """
INFO: アプリ起動したよ。
WARN: モジュールXで問題発見。
ERROR: ネットワークの致命的エラー。
INFO: アプリ終了。
""";
// ログファイルに複数行書き込む
File.WriteAllText(logFilePath, text);
// ループの各イテレーションで1行ずつ読み込んで処理
foreach (string line in File.ReadLines(logFilePath))
Console.WriteLine($"- {line}");
メリット:ファイルを部分的に読み込むから、大きなファイルでもメモリ消費がめっちゃ少ない。
File.ReadLines()とFile.ReadAllLines()の違い:
- File.ReadAllLines(path):全行を一気にメモリに読み込んで、string[]で返す。全行に一度にアクセスしたい時(ソートや検索など)に便利。
- File.ReadLines(path):IEnumerable<string>を返して、1行ずつループで読める。超でかいファイルでもメモリ効率が良い。
4. 文字列配列の書き込み
例えば、何かのコレクションから得た文字列リストを、1行ずつファイルに書き込みたい時があるよね。
File.WriteAllLines(path, contents)
このメソッドは文字列配列(またはコレクション)を受け取って、各要素を1行ずつファイルに書き込む。WriteAllText()同様、既存ファイルは上書きされる。
string membersFilePath = "participants.txt";
string[] names = { "イワン・ペトロフ", "マリヤ・シドロワ", "セルゲイ・コズロフ", "アンナ・クズネツォワ" };
// 配列の各行をファイルに書き込む
File.WriteAllLines(membersFilePath, names);
// 内容をチェック
Console.WriteLine($"'{membersFilePath}' の内容:");
foreach (string line in File.ReadLines(membersFilePath))
Console.WriteLine($"- {line}");
5. バイナリファイルの操作
Fileクラスはテキストだけじゃなく、バイナリデータの読み書きもできる。例えば、独自フォーマットの設定保存や画像・音声など、テキストじゃないデータにも便利。
バイト配列の書き込み:File.WriteAllBytes() 指定ファイルを作成または上書きして、渡したバイト配列を全部書き込む。
string binaryDataPath = "settings.bin";
// バイナリデータ例:画像、動画、何でもOK
byte[] settingsData = { 0x01, 0x0A, 0x2C, 0xFF, 0x00, 0x3F }; // なんかの「生」設定
File.WriteAllBytes(binaryDataPath, settingsData);
Console.WriteLine($"バイナリデータを '{binaryDataPath}' に書き込んだよ。");
注意:‘settings.bin’をメモ帳で開くと、読めない文字(文字化け)が出るよ。これはテキストじゃなくてバイト列だから。
バイト配列の読み込み:File.ReadAllBytes() バイナリファイルの内容を全部バイト配列で読む。
if (File.Exists(binaryDataPath))
{
byte[] readSettings = File.ReadAllBytes(binaryDataPath);
Console.WriteLine($"'{binaryDataPath}' から {readSettings.Length} バイト読み込んだ。");
Console.Write("読み込んだバイト(16進表示):");
foreach (byte b in readSettings)
Console.Write($"{b:X2} "); // :X2で2桁の16進数にフォーマット
Console.WriteLine();
}
else
{
Console.WriteLine($"エラー: バイナリファイル '{binaryDataPath}' が見つからない。");
}
これらのメソッドは、小さめのバイナリデータ(小さい画像やシリアライズ済みオブジェクトのキャッシュなど)に便利だよ。
6. ディスク上のファイル管理
Fileクラスはディスク上のファイル管理メソッドも持ってる。
ファイル存在チェック:File.Exists(path) 指定パスのファイルがあればtrue、なければfalseを返す。読み込みや削除など、ファイルが無いと困る操作の前には必ず使おう。
string myFileToCheck = "report.txt";
// 例としてまず作成
File.WriteAllText(myFileToCheck, "テストレポート。");
if (File.Exists(myFileToCheck))
{
Console.WriteLine($"ファイル '{myFileToCheck}' が見つかった。");
// ここから安全に読み込みや削除などできる
}
else
{
Console.WriteLine($"ファイル '{myFileToCheck}' が見つからない。");
}
ファイル削除:File.Delete(path) ファイルを完全に削除する。注意!これは元に戻せないよ!
string fileToDelete = "temp_file.txt";
// 例として作成
File.WriteAllText(fileToDelete, "このファイルは削除されるよ。");
if (File.Exists(fileToDelete))
{
File.Delete(fileToDelete);
Console.WriteLine($"ファイル '{fileToDelete}' を削除したよ。");
}
else
{
Console.WriteLine($"ファイル '{fileToDelete}' は既に無いか、前に削除されたみたい。");
}
7. ファイル操作時の例外
ファイル操作はOSや外部リソースとのやりとりだから、エラーが起きやすい。
例外(エラー)はちゃんと処理しよう! ファイル操作中はいろんな問題が起こる可能性があるから、プログラムが「落ちる」だけじゃなく、ちゃんと対処できるようにしよう。よくあるケース:
- FileNotFoundException:指定パスにファイルが存在しない。
- DirectoryNotFoundException:ファイルを作成/検索しようとしたフォルダが存在しない。
- UnauthorizedAccessException:読み書きや削除の権限が無い(システムファイルや保護領域など)。
- IOException:一般的なI/Oエラー(他のプログラムがファイルを開いてロックしてる、ディスク容量不足など)。
ファイル操作は必ずtry-catch構文で安全にやろう。エラーを「キャッチ」して、ユーザーにメッセージを出したりログに記録したりできる。
string sensitiveFilePath = "secret_data.txt";
try
{
// 存在しないか、権限が無いファイルを読もうとする例
string secretContent = File.ReadAllText(sensitiveFilePath);
Console.WriteLine($"シークレット内容を読み込んだ: {secretContent}");
}
catch (FileNotFoundException) // ファイルが見つからない
{
Console.WriteLine($"エラー: ファイル '{sensitiveFilePath}' が見つからない。パスを確認してね。");
}
catch (IOException ex) // 一般的なI/Oエラー(例:ファイルがロック中)
{
Console.WriteLine($"ファイル '{sensitiveFilePath}' のI/Oエラー: {ex.Message}");
}
catch (Exception ex) // その他予期しないエラー
{
Console.WriteLine($"予期しないエラーが発生: {ex.Message}");
}
8. System.IO.Fileがベストじゃない場合は?
Fileクラスは超万能だけど、使うべきじゃない(または使えない)シナリオもある:
超巨大ファイル(数十GB以上): ReadAllText()/ReadAllBytes()はファイル全体をメモリに読み込む。超でかいファイルだとOutOfMemoryExceptionになる。そういう時はFile.ReadLines()(テキスト用)や、ストリーム(Streams)(FileStream)で部分的に読み書きしよう(ストリームは次回レクチャーでやるよ)。
ファイルアクセスの細かい制御: ファイルをどう開くか(例:排他アクセスで他プロセスから読めないようにする、逆に複数プロセスで同時読み込みしたい等)を細かく制御したい場合、Fileでは無理。もっと低レベルなストリームクラスが必要。
非同期操作: 高速なアプリ(例:Webサーバー)で、ファイル操作中にメインスレッドをブロックしたくない場合は、非同期メソッド(ReadAllTextAsync()など)が必要。これもストリームベース。
部分的な読み書き: ファイルの一部だけを特定の位置から読みたい、既存ファイルの途中に書き込みたい、みたいな時はFileのメソッドじゃ無理。ストリームで直接アクセスしよう。
9. まとめ
なぜSystem.IO.Fileは人気なの?
- シンプル&簡潔: staticメソッドで複雑な操作も1〜2行でOK。開発が楽だし、コードも読みやすい。
- リソース自動管理: Fileは各操作ごとにファイルの開閉を自動でやってくれるから、リソース管理でミスしにくい。
- 日常タスクに万能: 小〜中サイズのテキスト・バイナリファイル操作なら、Fileで十分。
- よく使われる: 実務や面接でもFileクラスの使い方は必須スキル。
- 複雑さを隠してくれる: OSとのやりとりのややこしさを全部隠して、分かりやすいインターフェースを提供してくれる。
よくある質問&補足
File.ReadAllText()で扱える最大ファイルサイズは?
数十MB(< 100 MB)くらいまでなら大体問題なし。それ以上(数百MB〜GB単位)はFile.ReadAllText()だとメモリ不足(OutOfMemoryException)になるかも。そういう時はFile.ReadLines()で1行ずつ読むか、もっと高度なストリーム処理を使おう(後で解説するよ)。
存在しないフォルダにファイルを作成/書き込みできる?
できない。File.WriteAllText()やFile.WriteAllBytes()などは親ディレクトリを自動作成しない。例えばC:\MyAppData\Logs\current.logに書き込みたい時、MyAppDataやLogsが無いとDirectoryNotFoundExceptionになる。まずSystem.IO.Directoryクラス(例:Directory.CreateDirectory("myfolder"))で必要なフォルダを作っておこう。
作成日・更新日・サイズなどを知りたい時は?
ファイルの詳細情報(作成日、最終更新日、サイズ、属性など)を知りたいなら、System.IO.FileInfoクラスを使おう。便利なプロパティがいっぱいあるよ。
GO TO FULL VERSION