web-dev-qa-db-ja.com

例外コード、または「ファイルがすでに存在します」タイプの例外の検出

この質問 に答えようとすると、そのファイルがすでに存在するときに新しいファイルを作成しようとしても、一意の例外タイプがスローされず、一般的な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?
}
17
GazTheDestroyer
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"); // =)
}

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

9
jgauffin

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

5
ThunderGr

編集:ファイルがすでに存在する場合に使用される別の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.
    }
}
4
yurish

@jgauffinを変更するには、C#6で、when句内でFile.Existsを使用して、catchブロックに入らないようにします。したがって、 実際のように動作します)専用例外

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"))
{
   //...
}
2
Arithmomaniac

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

FileMode.Create

の代わりに

FileMode.CreateNew

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

0
Vytalyi

できません。残念ながら、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.

0

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を使用して存在する場合は上書きします。間違ったタイミングで作成されたファイルを上書きするという理論上のリスクがある場合でも、ほとんどのアプリはこのように機能すると思います。

0
Joe

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でも機能します。)

0
Søren Løvborg