C#のファイル操作におけるパフォーマンス改善のポイントを学ぼう【初心者向けガイド】
生徒
「C#でファイルを操作するとき、動きが遅いことがあるんですが、もっと速くする方法ってありますか?」
先生
「ファイル操作は工夫するだけで、大きくパフォーマンスが変わりますよ。特に大量のデータを読むときや書くときは差が大きくなります。」
生徒
「具体的にはどんな工夫をすればいいんですか?」
先生
「それでは、C#でファイル操作を高速化する基本ポイントを順番に見ていきましょう。」
1. C#のファイル操作はなぜ遅くなるのか?
C#でファイル操作を行うとき、パフォーマンスが落ちる理由はいくつかあります。特に初心者の方は、ファイルの読み書きがパソコンの記憶装置(ストレージ)に直接アクセスしているという点を理解するとイメージしやすくなります。ストレージはメモリよりも動作が遅いため、頻繁な読み書きを行うほどパフォーマンスが下がります。また、小さな読み書きを何度も繰り返すと、余計な回数ストレージにアクセスしてしまい、結果として処理が重くなります。
2. バッファリングを活用して効率よく読み書きしよう
バッファリングとは、一度に少しずつアクセスする代わりに、ある程度まとまったデータをまとめて読み書きする方法です。コンビニで一つずつ商品をレジに運ぶよりも、かごにまとめて運んだほうが速いイメージです。
C#ではBufferedStreamや、デフォルトでバッファリングが有効なStreamReader・StreamWriterを活用することで、ファイル操作が効率化されます。
using (var fs = new FileStream("sample.txt", FileMode.Open))
using (var bs = new BufferedStream(fs))
using (var sr = new StreamReader(bs))
{
string text = sr.ReadToEnd();
Console.WriteLine(text);
}
3. 一度に全部読む方法を検討しよう(ReadAllLines / ReadAllText)
ファイルサイズがそこまで大きくない場合は、File.ReadAllTextやFile.ReadAllLinesのように、まとめて読み込む方法が効果的です。これはファイルを丸ごとメモリに取り込み、一気に読み終えるため高速です。
ただし、ファイル容量が大きすぎる場合にはメモリを圧迫するので注意が必要です。
string text = File.ReadAllText("data.txt");
Console.WriteLine(text);
4. FileStreamのバッファサイズを調整して高速化しよう
C#のFileStreamは内部バッファを持っていますが、必要に応じてこのサイズを調整するとパフォーマンスが改善される場合があります。例えば、大きなファイルを読み書きする際には、バッファサイズを大きくすると効率が良くなります。
バッファサイズとは、一度にどれだけのデータをまとめて処理するかを決める数値で、数値を大きくするとまとめて処理できる量も増えます。
int bufferSize = 1024 * 64; // 64KB
using (var fs = new FileStream("bigfile.bin", FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize))
{
byte[] buffer = new byte[bufferSize];
int read = fs.Read(buffer, 0, buffer.Length);
}
5. 非同期(async/await)を使って処理を軽くしよう
ファイルの読み書きが重いと、パソコンがその処理に集中してしまい、他の処理が止まってしまうことがあります。非同期処理(async/await)を使えば、ファイル操作中もプログラムが固まらず、動作がスムーズになります。
これは、重い処理を裏側に任せながら、他の処理を進められるしくみです。
using (var fs = new FileStream("log.txt", FileMode.Open, FileAccess.Read))
{
byte[] buffer = new byte[1024];
int read = await fs.ReadAsync(buffer, 0, buffer.Length);
}
6. ループ内で小さな書き込みを繰り返さない工夫
初心者がよくやってしまうのが、ループの中で小さな書き込みを何度も行うコードです。これは非常に非効率で、ファイルに何度もアクセスしてしまいます。
改善方法は「一度文字列をまとめてから書き込む」ことです。メールを書いているときに、一文字入力するたびに送信するのではなく、文章を全部書いてから送信するようなイメージです。
var lines = new List<string>();
for (int i = 0; i < 10000; i++)
{
lines.Add($"Line {i}");
}
File.WriteAllLines("output.txt", lines);
7. usingを使ってファイルを早く解放しよう
ファイルを開きっぱなしにすると、ほかのプログラムがそのファイルを使えなくなり、無駄な待ち時間が発生することがあります。C#ではusing文を使うことで、ファイルを自動で閉じてくれるため、余計なリソース消費を防ぎます。
これは、使い終わった道具をすぐ片付ける習慣のようなものです。
8. 文字コード(エンコーディング)を適切に選ぶ
ファイルの文字コードを適切に選ぶこともパフォーマンスに影響します。特に、UTF-8やUTF-16などの文字コードは変換処理が行われるため、適切な形式を選ぶことで無駄な処理を防げます。大量のテキストを扱う場合には、読み書きの文字コードを統一することで性能が安定します。
9. メモリストリーム(MemoryStream)を使って高速処理
一時的にデータを扱いたいだけなら、ファイルではなくメモリにデータを置けるMemoryStreamを使う方法があります。これはストレージを使わないため、とても高速です。
ただし、大量のデータを扱うとメモリを圧迫するため、用途に合わせて使うことが大切です。