C - Countを持つファイルへの書き込み方法- StackOverflowは正しくはありません


今日のヒントは、ASPのホットな新バージョンについて正確にはありません.ネットコアまたはそのようなもの.私は多くの場合、どのように迅速かつ効果的な方法でファイルにテキストを書くように私自身のgoogling“単純な”質問を見つける.ほとんどの結果は、ブログの投稿を使用しています.例としてNET 2、または2010年からスタックオーバーフローの回答.すべてのサンプルに共通のコードの重要なラインだけが追加され、エラー処理のような重要な側面に焦点が強調表示されません.このポストは、新しいhow-to series そして、私が長年にわたって学んだことを合計する私の試み.

ファイル.writetext
文字列をファイルに書き込む最初の例はFile.WriteAllText メソッド.私が最初の例としてこれを言及した理由は、それが95 %(多分より多く)であるからです人々がやっている.そして、私はなぜ私が何年もこれをしていた時から理解しています.このアプローチの単純さを見てみましょう.
var writeMe = "File content";
File.WriteAllText("output.txt", writeMe);
この例では、output.txt の内容でwriteMe 変数.このアプローチは、より小さいテキストファイルのために細かくなりますが、大量のデータを扱うとき、デフォルトの選択であるべきではありません.
残りのポストのためにシナリオを作成しましょうWriteAllText データをファイルに書き込むには、次の手順に従います.
var sb = new StringBuilder();
var lines = Enumerable
    .Range(1, 1000000)
    .Select(i => $"Line number {i}")
    .ToList();
lines.ForEach(i => sb.AppendLine($"Line number {i}"));

var content = sb.ToString();
File.WriteAllText("output.txt", content);
例では、100万行を生成し、output.txt ファイル.私のマシンでは、ほとんどのシナリオではかなり印象的です.

ファイル.CreateText
ここでWriteAllText メソッドはすべてを一度に書きます.再利用しましょうStringBuilder 前に、これを使用する方法を説明するFile.CreateText メソッド:
using (var writer = File.CreateText("output2.txt"))
{
    foreach (var line in lines)
    {
        writer.WriteLine(line);
    }
}
The CreateText メソッドはStreamWriter 複数の行をファイルに公開したり、ファイルに書き込むことができるオブジェクトchar 一度に.を処分するときStreamWriter , バッファーは基になるストリームにフラッシュされ、ファイルハンドルが解放されます.手動で呼び出すことができますFlush 同じ結果を得るメソッドです.

盛衰
何度も見たことがある.顧客の苦情は、UIが“ハング”何かをクリックするときに読み取りまたは大きなファイルに書き込みを含むハングします.あなたは、おそらく、これがどこに行っているかについてわかっています?async !
ファイルに非同期に書き込むための良い選択.NETはFileStream クラス.使用する前に例をポートしましょうFileStream . まず、同期例を示します.
using (var stream = new FileStream(
    "output3.txt", FileMode.Create, FileAccess.Write, FileShare.Write, 4096))
{
    var bytes = Encoding.UTF8.GetBytes(content);
    stream.Write(bytes, 0, bytes.Length);
}
例では、FileStream 使用するときには、ストリームを一度で処理することはできません.あなたは主にWrite 1つ以上のバイトを基になるストリームに書き込みます.を呼び出すことができますWrite メソッド複数回、これはデータベースレコードのような何かを繰り返して、同じファイルに各レコードを書き込む必要があるとき、これは良い選択になります.
使用FileStream は通常、最後の2つの例からのメソッドよりも速い.このポストのために生成されたデータを保存するとき、FileStream 他の例より約20 %速い.さらに迅速に実行しているとき.ネットコア.
次に非同期バージョンについて:
using (var stream = new FileStream(
    "output4.txt", FileMode.Create, FileAccess.Write, FileShare.Write, 4096, useAsync:true))
{
    var bytes = Encoding.UTF8.GetBytes(content);
    await stream.WriteAsync(bytes, 0, bytes.Length);
}
追加しましたtrue ( useAsync パラメータFileStream コンストラクタ.これはFileStream 非同期IOを使用するにはそれから私はWriteAsync メソッドの代わりにWrite 前のサンプルからのメソッド.また、覚えておいてくださいawait メソッド.
最後の例でのAsyncコードのパフォーマンスを見ると、パフォーマンスは2つの最初の例に対応します.では、なぜasyncFileStream 同期するより遅いとき?もちろん、メインスレッドのブロックを避けるためです.

NETコア
簡単に触れた.NETコアの前の例の1つです.私は、我々がポストで使用したAPIがすべて同じ署名を共有するとあなたに話すのをうれしく思います.ネットコア.これは、プロジェクトを切り替えることができます.NETコアと上記のすべてのコンパイルエラーなしで上記の例を再コンパイルします.
例を実行すると、コードのすべてが5〜10 ms速く実行されます.間の違い.NETフルフレームワークと.ネットコアは、もちろん、あなたの要件に依存するでしょう.

例外処理
ファイルへの書き込みの見落とされがちな(特に重要な)側面は例外処理です.ファイルシステムと相互作用するとき、多くのものは間違って行くことができます.心配する必要のある2つのグループがあります.
  • パスの問題.
  • ディスクへの書き込み中の問題.
  • 各グループに掘る前に、例外処理をFile.WriteAllText 例:
    try
    {
        File.WriteAllText("c:\\temp\\output.txt", "Hello World");
    }
    catch (DirectoryNotFoundException dirNotFoundException)
    {
        // Create and try again
    }
    catch (UnauthorizedAccessException unauthorizedAccessException)
    {
        // Show a message to the user
    }
    catch (IOException ioException)
    {
        logger.Error(ioException, "Error during file write");
        // Show a message to the user
    }
    catch (Exception exception)
    {
        logger.Fatal(exception, "We need to handle this better");
        // Show general message to the user
    }
    

    Please note that implementing control flow using exceptions is considered a bad practice. While the code above serves well as an example, you probably want to check common scenarios like a directory not found before trying to write to a file.



    パスの問題
    ファイルを扱うときに例外が発生する可能性のあるさまざまな問題があります.私は、すでにこれらのカップルについてここでブログしました:Debugging System.IO.FileNotFoundException - Cause and fix and Debugging System.UnauthorizedAccessException (often followed by: Access to the path is denied) .
    コードキャッチをtry catchでファイルにラップして、次の例外が発生した場合に何が起こるかを決める必要があります.
  • DirectoryNotFoundException
  • UnauthorizedAccessException
  • いくつかの例外は、あなたのコードによって自動ヒーリングとして実装することができます(不足しているディレクトリを作成して、再びファイルを書くために書くように)、他のものがメッセージをあなたのログに書かれるユーザーまたはログメッセージにもたらすでしょう.

    ディスクへの書き込み中の問題
    他の例外はファイルにコンテンツを書き込む際に問題に対処します.一旦ファイルが作成されることができて、新しいファイルを含むディレクトリが存在して、プロセスが十分なアクセスをするということを知っているならば、多数のものはまだ間違って行くことができます.
    実際の書き込み中に起こるほとんどの問題は、IOException . IOException ほとんどのファイル関連の例外の基底クラスはとにかくです.したがって、それぞれのサブクラスをキャッチして、それに応じて異なるシナリオを扱うことができます.

    あなたのユーザーは、より少しの誤りを評価しますか?
    エルマ.IOは簡単なエラーログとアップタイム監視サービスです.ネットすべてのサポートを使用してエラーのコントロールを取り戻す.NET Webおよびログフレームワーク.
    ➡️ Error Monitoring for .NET Web Applications ⬅️
    この記事はエルマに初めて現れた.ioのブログhttps://blog.elmah.io/how-to-write-to-a-file-with-csharp-stackoverflow-doesnt-get-it-right/