web-dev-qa-db-ja.com

ファイル/ディレクトリが存在するかどうかを確認してください:より良い方法はありますか?

ファイル名が使用されていないことを確認するためだけに、これを頻繁に行っています。もっと良い方法はありますか?

Directory.Exists(name) || File.Exists(name)
40
user34537

確かに:)

internal static bool FileOrDirectoryExists(string name)
{
   return (Directory.Exists(name) || File.Exists(name));
}
56
PaulG

Exists()を使用してファイル名またはディレクトリ名を確認しているという事実使用中は、競合状態の影響を受けることに注意してください。

Exists()テストが合格した後の任意の時点で、たとえば、コードがファイルを作成するポイントに到達する前に、何かがその名前のファイルを作成する可能性があります。

(ファイルが既に存在する例外的な条件であると仮定しています)。

適切なFileShareパラメーターを指定して、単にファイルを開く方が信頼性が高くなります。

例:

using System;
using System.IO;

static class FileNameInUse
{
    static void Main(string[] args)
    {
        string path = args[0];
        using (var stream = File.Open(path, FileMode.CreateNew, FileAccess.Write, FileShare.None))
        {
            // Write to file
        }
    }
}

そのため、失敗時にIOExceptionを処理するだけで、コードがより単純になり、競合状態が発生しにくくなります。

  • 他の何かが既にファイルを作成している場合、FileMode.CreateNewIOExceptionをスローします
  • FileShare.Noneが原因で、開いて作成が成功した場合、閉じるまで他のプロセスはファイルにアクセスできません。

残念ながら、ファイルが現在使用中であるかどうかを確認することはできず、exceptionいP/Invokeなしで例外をスローしません。

    bool IsFileInUse(string fileName)
    {
            IntPtr hFile = Win32.CreateFile(fileName, Win32.FILE_READ_DATA, 0, IntPtr.Zero, Win32.OPEN_EXISTING, Win32.FILE_ATTRIBUTE_NORMAL, IntPtr.Zero);
            if (hFile.ToInt32() == Win32.INVALID_HANDLE_VALUE)
                return true;

            Win32.CloseHandle(hFile);
            return false;
    }

    class Win32
    {
        const uint FILE_READ_DATA = 0x0001;
        const uint FILE_SHARE_NONE = 0x00000000;
        const uint FILE_ATTRIBUTE_NORMAL = 0x00000080;
        const uint OPEN_EXISTING = 3;
        const int INVALID_HANDLE_VALUE = -1;

        [DllImport("kernel32.dll", SetLastError=true)]
        internal static extern IntPtr CreateFile(string lpFileName,
                                               uint dwDesiredAccess,
                                               uint dwShareMode,
                                               IntPtr lpSecurityAttributes,
                                               uint dwCreationDisposition,
                                               uint dwFlagsAndAttributes,
                                               IntPtr hTemplateFile);

        [DllImport("kernel32.dll")]
        internal static extern bool CloseHandle(IntPtr hObject);
    }

また、この高速チェックは、ファイルハンドルを返さず、関連するFileStreamコンストラクターに渡さない限り、競合状態になりやすいです。

34
Leon Breedt

それが唯一の方法だと思います。通常、指定したものを含むI/Oメソッドをカプセル化する静的メソッドを持つ「FileManager」クラスがあり、その「FileManager」をすべてのアプリケーションでライブラリとして使用します。

4
Ashish Gupta

これを確認する私の方法は、 FileSystemInfo を使用することです。これが私のコードです。

FileSystemInfo info = 
  File.GetAttributes(data.Path).HasFlag(FileAttributes.Directory) ? 
    new DirectoryInfo(data.Path) : (FileSystemInfo)new FileInfo(data.Path);

return info.Exists;

ファイルが存在するかどうかを確認する別の方法。

FileInfo file = new FileInfo("file.txt");

if (file.Exists)
{
    // TO DO
}
2
Anonymous

次の機能を使用できます。

[DllImport("shlwapi", EntryPoint = "PathFileExists", CharSet = CharSet.Unicode)]
public static extern bool PathExists(string path);
0
TN.