如何尝试创建文件,并返回一个指示是否已创建的值?

时间:2012-07-25 14:24:13

标签: c# .net windows file-io .net-4.0

我正在寻找类似于这样的签名的东西:

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 :我们可以假设在执行此代码时不会从目录中删除文件。

3 个答案:

答案 0 :(得分:3)

不,没有直接的方法也没有办法避免异常处理。

即使您尝试打开现有文件,例如

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

你仍然可以获得各种异常,包括FileNotFound。

这是因为你提到的所有原因:

  

跨线程,进程甚至其他机器

但你可能想看看System.IO.Path.GetRandomFileName()。我认为他的i基于WinAPI函数,可以指定路径等。

答案 1 :(得分:1)

以这种方式尝试:

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

实际上没有更好的方法来检查文件是否已创建。没有任何内置功能。<​​/ p>

答案 2 :(得分:0)

这实际上是一个非常复杂的问题。

拥有真正的线程安全方法非常困难。在您的TryCreateFile中,想象一下,在您测试File.Exists之前,有人会在创建文件后立即从另一个进程中删除该文件?你的代码会抛出异常。

如果您的主要目标是

  

创建&#34; next&#34;目录和的顺序空文件   返回其路径

,我不会尝试测试文件是否存在。我假设一个带有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是否真正独特的人,请参阅Is a GUID unique 100% of the time?