Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何尝试创建一个文件,并返回一个值,指示是否创建了该文件?_C#_.net_Windows_File Io_.net 4.0 - Fatal编程技术网

C# 如何尝试创建一个文件,并返回一个值,指示是否创建了该文件?

C# 如何尝试创建一个文件,并返回一个值,指示是否创建了该文件?,c#,.net,windows,file-io,.net-4.0,C#,.net,Windows,File Io,.net 4.0,我正在寻找类似的东西,上面会有这样的签名: 静态bool TryCreateFile(字符串路径); 这需要避免线程、进程甚至其他访问同一文件系统的机器之间的潜在竞争条件,而不需要当前用户拥有比File.Create更多的权限。目前,我有以下代码,我并不特别喜欢: 静态bool TryCreateFile(字符串路径) { 尝试 { //如果我们能够成功创建文件, //返回true并关闭它。 使用(File.Open(路径,FileMode.CreateNew)) { 返回true; } }

我正在寻找类似的东西,上面会有这样的签名:

静态bool TryCreateFile(字符串路径);
这需要避免线程、进程甚至其他访问同一文件系统的机器之间的潜在竞争条件,而不需要当前用户拥有比
File.Create更多的权限。目前,我有以下代码,我并不特别喜欢:

静态bool TryCreateFile(字符串路径)
{
尝试
{
//如果我们能够成功创建文件,
//返回true并关闭它。
使用(File.Open(路径,FileMode.CreateNew))
{
返回true;
}
}
捕获(IOException)
{
//如果File.Open调用失败,我们希望重新显示异常
//而不是因为它已经存在。
如果(!File.Exists(path))
{
投掷;
}
}
返回false;
}
有没有别的方法让我错过了

这适用于下面的helper方法,该方法旨在为目录创建“下一个”顺序空文件并返回其路径,从而再次避免线程、进程甚至访问同一文件系统的其他机器之间的潜在争用情况。因此,我想一个有效的解决方案可能涉及一种不同的方法:

静态字符串GetNextFileName(字符串目录路径)
{
while(true)
{
IEnumerable fileNumbers=目录.枚举文件(目录路径)
.Select(int.Parse)
.Cast();
int nextNumber=(fileNumbers.Max()??0)+1;
字符串文件名=Path.Combine(directoryPath,nextNumber.ToString());
if(TryCreateFile(文件名))
{
返回文件名;
}
}
}

Edit1:我们可以假设在执行此代码时不会从目录中删除文件。

请尝试以下方法:

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

实际上,并没有更好的方法来检查文件是否已创建。没有任何类型的inbuid函数。

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

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

if (File.Exists(fName))
   var s = File.OpenRead(fname);
您仍然可以获得各种异常,包括FileNotFound

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

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


但是您可能想看看
System.IO.Path.GetRandomFileName()
。我认为他的I基于一个WinAPI函数,该函数允许您指定路径等。

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

很难找到真正的线程安全方法。在您的
TryCreateFile
中,假设有人在创建文件之后,在您测试
文件之前,从另一个进程中删除了该文件。是否存在
?您的代码将引发异常

如果你的主要目标是

为目录创建“下一个”连续空文件,并 返回其路径

,我不会尝试测试文件是否存在。我假设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是否真正唯一的人,请参见

您是故意关闭(而不是返回)创建的文件流的吗?请注意,如果没有文件,fileNumbers.Max()将引发异常。@HenkHolterman-是的,这是故意的。代码将创建一个带有该文件名的空文件(确保其他线程、进程和机器将在其上拾取该文件)。如果没有抛出,则该文件名是好的。@Carra-由于调用了
.Cast()
函数,如果没有文件,则返回
null
,然后将合并为零。@Joe-检查msdn页面,当IEnumerable中没有元素时,它会抛出InvalidOperationException。您提出了一个有效点——请参见上面的编辑:我们可以假设在执行此代码时不会从目录中删除文件。就GUID的想法而言——我考虑使用GUID来确保唯一性,并使用FileInfo.CreationTime来获得订单;因为FileInfo.CreationTime的分辨率为1ms,但是,当请求的文件在时间上彼此非常接近时,存在反转的可能性,因此我们不能依赖于此。@JoeAmenta你说了一些有趣的事情,我在第一次阅读你的问题时没有理解:文件创建顺序对你很重要。请添加更多关于创建后如何
使用
文件的背景信息,也许可以基于安全GUID方式提供一个很好的答案。顺便说一句,我编辑了最初的答案,增加了一些关于guid的精确性。