19

何らかの方法でファイルを操作していることに気付くことがよくありますが、コードを書いた後は、実際にどれだけ壊れているのか常に確信が持てません。問題は、ファイル関連の操作がどのように失敗する可能性があるか、つまり期待を処理する最善の方法が完全にはわからないことです。

簡単な解決策は、コードによってスローされた IOExceptions をキャッチし、ユーザーに「アクセスできないファイル」エラー メッセージを表示することですが、もう少し細かいエラー メッセージを表示することは可能です。別のプログラムによってファイルがロックされているなどのエラーと、ハードウェア エラーが原因でデータが読み取れないエラーの違いを判断する方法はありますか?

次の C# コードが与えられた場合、ユーザー フレンドリーな (できるだけ有益な) 方法でエラーを処理するにはどうすればよいでしょうか?

public class IO
{
   public List<string> ReadFile(string path)
   {
      FileInfo file = new FileInfo(path);

      if (!file.Exists)
      {
         throw new FileNotFoundException();
      }

      StreamReader reader = file.OpenText();
      List<string> text = new List<string>();

      while (!reader.EndOfStream)
      {
         text.Add(reader.ReadLine());
      }

      reader.Close();
      reader.Dispose();
      return text;
   }

   public void WriteFile(List<string> text, string path)
   {
      FileInfo file = new FileInfo(path);

      if (!file.Exists)
      {
         throw new FileNotFoundException();
      }

      StreamWriter writer = file.CreateText();

      foreach(string line in text)
      {
         writer.WriteLine(line);
      }

      writer.Flush();
      writer.Close();
      writer.Dispose();
   }
}
4

6 に答える 6

15

...しかし、もう少し細かいエラー メッセージを取得することは可能ですか。

はい。先に進み、 catchメソッドをIOException使用してException.ToString()、比較的関連性の高いエラー メッセージを表示します。.NET Framework によって生成された例外は、これらの便利な文字列を提供しますが、独自の例外をスローする場合は、次のExceptionように、その文字列を のコンストラクターにプラグインすることを忘れないでください。

throw new FileNotFoundException("File not found");

また、絶対に、Scott Dormanusingに従って、そのステートメントを使用してください。ただし、このusingステートメントは実際にはcatch何もしていないことに注意してください。たとえば、ファイルが存在するかどうかを確認するテストでは、かなり厄介な競合状態が発生します。入れても何の得にもなりません。だから、今、読者のために私たちは持っています:

try {  
    using (StreamReader reader = file.OpenText()) {  
        // Your processing code here  
    }  
} catch (IOException e) {  
    UI.AlertUserSomehow(e.ToString());  
}

要するに、基本的なファイル操作の場合: 1.
使用 2 using
、using ステートメントまたは関数をtry/catchcatch囲みます 。.NET にスローを任せてください。IOException
Exception.ToString()catch

于 2008-09-18T07:03:21.767 に答える
7

最初に変更する必要があるのは、次のように、StreamWriter と StreamReader の呼び出しを using ステートメントでラップすることです。

using (StreamReader reader = file.OpenText())
{
   List<string> text = new List<string>();
   while (!reader.EndOfStream)
   {
      text.Add(reader.ReadLine());
   }
}

これにより、Close と Dispose の呼び出しが処理され、実際に try/finally ブロックでラップされるため、実際のコンパイル済みコードは次のようになります。

StreamReader reader = file.OpenText();
try
{
   List<string> text = new List<string>();
   while (!reader.EndOfStream)
   {
      text.Add(reader.ReadLine());
   }
}
finally
{
   if (reader != null)
      ((IDisposable)reader).Dispose();
}

ここでの利点は、例外が発生した場合でもストリームが確実に閉じられることです。

より明示的な例外処理に関する限り、それは実際に何をしたいかによって異なります。あなたの例では、ファイルが存在するかどうかを明示的にテストし、ユーザーにとっては十分な FileNotFoundException をスローしますが、そうでない場合もあります。

于 2008-09-17T19:43:39.357 に答える
1

ファイルの存在を確認し、メッセージなしでFileNotFoundExceptionをスローする意味がわかりません。フレームワークは、メッセージとともにFileNotFoundException自体をスローします。

この例のもう1つの問題は、try / finalパターンまたはusingステートメントを使用して、例外が発生した場合でも使い捨てクラスが適切に破棄されるようにする必要があることです。

これを次のように実行し、メソッドの外部で例外をキャッチして、例外のメッセージを表示します。

public IList<string> ReadFile(string path)
{
    List<string> text = new List<string>();
    using(StreamReader reader = new StreamReader(path))
    {
      while (!reader.EndOfStream)      
      {         
         text.Add(reader.ReadLine());      
      }
    }
    return text;
}
于 2008-09-17T19:52:15.810 に答える
1
  • File.Exists(); をスキップします。他の場所で処理するか、CreateText()/OpenText() で発生させます。
  • エンドユーザーは通常、成功するかどうかだけを気にします。それが失敗した場合は、そう言ってください、彼は詳細を望んでいません.

.NET で何かが失敗した理由と原因について詳細を取得する組み込みの方法は見つかりませんでしたが、CreateFile をネイティブに使用すると、何が問題なのかを示す何千ものエラー コードが得られます。

于 2008-09-17T19:49:07.737 に答える
0

おそらくこれはあなたが探しているものではありませんが、例外処理を使用している種類を再考してください。最初は、少なくともプログラマーをユーザーと考える限り、例外処理を「ユーザーフレンドリー」として扱うべきではありません。

その要約は、次の記事http://goit-postal.blogspot.com/2007/03/brief-introduction-to-exception.htmlである可能性があります。

于 2008-09-17T19:55:14.897 に答える
0

ファイルを簡単に閉じるには、using ステートメントを使用します。MSDN の C# using ステートメントを参照してください

MSDN から:

  using (TextWriter w = File.CreateText("log.txt")) {
     w.WriteLine("This is line one");
     w.WriteLine("This is line two");
  }
  using (TextReader r = File.OpenText("log.txt")) {
     string s;
     while ((s = r.ReadLine()) != null) {
        Console.WriteLine(s);
     }
  }
于 2008-09-17T19:49:16.237 に答える