5

私はこのような署名を持つものに似たものを探しています:

static bool TryCreateFile(string path);

これは、現在のユーザーが必要以上の権限を持っている必要なしに、スレッド、プロセス、さらには同じファイルシステムにアクセスする他のマシン間での潜在的な競合状態を回避する必要がありFile.Createます。現在、私は次のコードを持っていますが、特に好きではありません。

static bool TryCreateFile(string path)
{
    try
    {
        // If we were able to successfully create the file,
        // return true and close it.
        using (File.Open(path, FileMode.CreateNew))
        {
            return true;
        }
    }
    catch (IOException)
    {
        // We want to rethrow the exception if the File.Open call failed
        // for a reason other than that it already existed.
        if (!File.Exists(path))
        {
            throw;
        }
    }

    return false;
}

私が見逃しているこれを行う別の方法はありますか?

これは、ディレクトリの「次の」シーケンシャルな空のファイルを作成してそのパスを返すように設計された次のヘルパーメソッドに適合し、スレッド、プロセス、さらには同じファイルシステムにアクセスする他のマシン間の潜在的な競合状態を回避します。したがって、有効な解決策には、これに対する別のアプローチが含まれる可能性があると思います。

static string GetNextFileName(string directoryPath)
{
    while (true)
    {
        IEnumerable<int?> fileNumbers = Directory.EnumerateFiles(directoryPath)
                                                 .Select(int.Parse)
                                                 .Cast<int?>();
        int nextNumber = (fileNumbers.Max() ?? 0) + 1;
        string fileName = Path.Combine(directoryPath, nextNumber.ToString());
        if (TryCreateFile(fileName))
        {
            return fileName;
        }
    }
}

Edit1:このコードの実行中は、ファイルがディレクトリから削除されないと想定できます。

4

3 に答える 3

3

いいえ、直接的な方法はなく、例外処理を回避する方法もありません。

既存のファイルを開こうとしても、

if (File.Exists(fName))
   var s = File.OpenRead(fname);

FileNotFoundを含む、あらゆる種類の例外を引き続き取得できます。

これはあなたが言及したすべての理由によるものです:

スレッド、プロセス、さらには他のマシン間

しかし、あなたは見てみたいかもしれませんSystem.IO.Path.GetRandomFileName()。彼のiは、パスなどを指定できるWinAPI関数に基づいていると思います。

于 2012-07-25T14:34:20.377 に答える
1

この方法で試してください:

    private bool TryCreateFile(string path)
    {
        try
        {
            FileStream fs = File.Create(path);
            fs.Close();
            return true;
        }
        catch 
        {
            return false;
        }
    }

実際には、ファイルが作成されているかどうかを確認する方法はありません。いかなる種類の組み込み関数もありません。

于 2012-07-25T14:28:08.883 に答える
0

これは実際には本当に複雑な問題です。

真のスレッドセーフな方法を持つのはかなり難しいです。あなたのTryCreateFile中で、あなたがテストする前に、誰かがファイルを作成した直後に別のプロセスから削除したと想像してみてくださいFile.Exists。コードは例外をスローします。

あなたの主な目標が

ディレクトリの「次の」シーケンシャル空ファイルを作成し、そのパスを返します

、ファイルが存在するかどうかをテストしようとはしません。名前は常に一意であるため、GUIDを含むファイルを想定します。

private static void Main(string[] args)
{
    var z = GetNextFileName(@"c:\temp");

    Console.ReadLine();
}

public static string GetNextFileName(string directoryPath)
{
    // Gets file name
    string fileName = Guid.NewGuid().ToString();
    string filePath = Path.Combine(directoryPath, fileName);

    // Creates an empty file
    using (var z = File.Open(filePath, FileMode.CreateNew))
    {
    }

    return filePath;
}

編集:GUIDが本当に一意であるかどうかを尋ねている人は、「GUIDは常に100%一意ですか?」を参照してください。

于 2012-07-25T16:56:49.170 に答える