22

この質問に答えようとすると、そのファイルがすでに存在するときに新しいファイルを作成しようとしても、一意の例外タイプがスローされず、ジェネリックがスローされるだけであることに驚きましたIOException

IOExceptionしたがって、が既存のファイルの結果なのか、それとも他のIOエラーの結果なのかを判断する方法がわからないままです。

例外にはHResultがありますが、このプロパティは保護されているため、使用できません。

私が見ることができる他の唯一の方法は、ひどい感じのメッセージ文字列をパターンマッチングすることです。

例:

try
{
    using (var stream = new FileStream("C:\\Test.txt", FileMode.CreateNew))
    using (var writer = new StreamWriter(stream))
    {
        //write file
    }
}
catch (IOException e)
{
    //how do I know this is because a file exists?
}
4

8 に答える 8

11
try
{
    using (var stream = new FileStream("C:\\Test.txt", FileMode.CreateNew))
    using (var writer = new StreamWriter(stream))
    {
        //write file
    }
}
catch (IOException e)
{
    var exists = File.Exists(@"C:\Text.text"); // =)
}

再度削除された可能性のある一時ファイルなどでは動作しません。

これが私の例外のベストプラクティスです:https ://coderr.io/exception-handling

于 2012-09-12T13:46:38.947 に答える
6

編集:ファイルがすでに存在する場合に使用される別のHresultがあります:0x800700B7 (-2147024713)「そのファイルがすでに存在する場合はファイルを作成できません」。コードサンプルを更新しました。


新しいファイルを作成しようとして、それがすでに存在する場合、IOExceptionにはがありHresult = 0x80070050 (-2147024816)ます。

したがって、コードは次のようになります。

try
{
    using (var stream = new FileStream("C:\\Test.txt", FileMode.CreateNew))
    using (var writer = new StreamWriter(stream))
    {
        //write file
    }
}
catch (IOException e)
{
    if (e.HResult == -2147024816 || 
        e.HResult == -2147024713)
    {
        // File already exists.
    }
}
于 2017-03-21T12:05:16.873 に答える
5

この条件は、IOExceptionのcatchステートメントに含めることができますif(ex.Message.Contains("already exists")) { ... }。これはハックですが、一時ファイルなどを含め、ファイルが存在するすべての場合に機能します。

于 2014-03-28T12:58:07.843 に答える
3

@jgauffinを変更するには、C#6で、句のFile.Exists内部を使用して、ブロックに入らないようにし、実際の専用例外のように動作させることができます。whencatch

try
{
    using (var stream = new FileStream("C:\\Test.txt", FileMode.CreateNew))
    using (var writer = new StreamWriter(stream))
    {
        //write file
    }
}
catch (IOException e) when (File.Exists(@"C:\Text.text"))
{
   //...
}
于 2016-06-23T18:31:55.623 に答える
2

100%絶対確実というわけではありませんが(IOExceptionには他の理由があります)、少なくとも派生したすべての例外タイプを除外できます。

try
{
    ...
}
catch(IOException e)
{
    if (e is UnauthorizedAccessException) throw;
    if (e is DirectoryNotFoundException) throw;
    if (e is PathTooLongException) throw;
    // etc for other exceptions derived from IOException

    ... assume file exists
}

または同等のもの:

try
{
    ...
}
catch(UnauthorizedAccessException)
{
    throw;
}
catch(DirectoryNotFoundException)
{
    throw;
}
catch(PathTooLongException)
{
    throw;
}
catch(IOException e)
{
    ... assume file exists
}

リンクされた質問については、存在を確認し、ユーザーに上書きするように促し、存在OpenOrCreateする場合はを使用して上書きします。間違ったタイミングで作成されたファイルを上書きするという理論上のリスクがある場合でも、ほとんどのアプリはこのように機能すると思います。

于 2012-09-12T14:03:08.337 に答える
0

できません。残念ながら、IOExceptionは、.NET Frameworkでの私の理解を超えて、何らかの理由でさらに指定されていません。

ただし、新しいファイルを作成する場合は、ファイルが最初に存在するかどうかを確認するのが一般的な方法です。そのようです:

       try
        {
            if (File.Exists("C:\\Test.txt"))
            {
                //write file

                using (var stream = new FileStream("C:\\Test.txt", FileMode.CreateNew))
                using (var writer = new StreamWriter(stream))
                {
                    //The actual writing of file

                }

            }
        }
        catch (IOException ex)
        {
            //how do I know this is because a file exists?
            Debug.Print(ex.Message);
        }

おそらくあなたが探していた答えではありません。しかし、c'est ca.

于 2012-09-12T14:02:57.683 に答える
0

C#6以降の場合:

const int WARN_WIN32_FILE_EXISTS = unchecked((int)0x80070050);

try
{
    ...
}
catch (IOException e) when (e.HResult == WARN_WIN32_FILE_EXISTS)
{
    ...
}

...またはwhen (e.HResult == -2147024816)、「迅速で侵入できない」場合。;-)

(FWIW、Windows中心のエラーコードはMonoによって忠実にコピーされており、Mac / Linuxでも機能します。)

于 2018-06-26T09:15:01.880 に答える
-1

あなたは使用する必要があります

FileMode.Create

それ以外の

FileMode.CreateNew

ファイルがすでに存在する場合は、ファイルを上書きします。

于 2012-09-12T13:47:49.073 に答える