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 回答