如何创建一个文件和任何文件夹(如果这些文件夹不存在)?

172

假设我想创建或覆盖以下文件:- C:\Temp\Bar\Foo\Test.txt

使用File.Create(..)方法可以实现。

但是,如果我没有以下任何一个文件夹(来自上述路径的示例)

  • Temp
  • Bar
  • Foo

那么就会抛出DirectoryNotFoundException

因此...给定一个路径,我们如何递归地创建所有必要的文件夹以创建该路径下的文件?如果Temp或Bar文件夹存在,但没有Foo,则也会创建它。

为简单起见,假设没有安全问题--所有权限都可以,等等。


1
可能是保存文件并自动创建目录的重复问题。 - mateuscb
可能是重复的问题:如果文件夹不存在,则创建它 - Michael Freidgeim
9个回答

186

总结其他答案中提到的内容:

//path = @"C:\Temp\Bar\Foo\Test.txt";
Directory.CreateDirectory(Path.GetDirectoryName(path));

Directory.CreateDirectory 方法会递归地创建目录,如果该目录已经存在,则不会出现错误。

但是,如果在指定的路径中存在同名文件 Foo,则会抛出异常。


如果你正在处理长路径(256+),请参考 https://dev59.com/sG435IYBdhLWcg3w1juV。 - Alexei Levenkov

139
DirectoryInfo di = Directory.CreateDirectory(path);
Console.WriteLine("The directory was created successfully at {0}.",
    Directory.GetCreationTime(path));

请参考此MSDN页面


89
如果目录已经存在,你可以毫无顾虑地调用Directory.CreateDirectory,不需要先检查Directory.Exists - 如果目录已经存在,它不会抛出异常。 - Tim Robinson
1
@Tim:不太确定,所以我随便加上了。不过还是谢谢你提供的信息。 - Christopher B. Adkins
28
别忘了Path.GetDirectoryName(string path),可以用它从完整路径中获取目录。 - Oliver
@Oliver:Directory和DirectoryInfo类有一整套的功能,但我提供的代码足以让他朝着正确的方向前进。我认为链接也有很多扩展信息。 - Christopher B. Adkins
10
请注意:变量 path 不应包含文件名。因此,使用 OP 的示例,path 应为 C:\Temp\Bar\Foo。在调用 Directory.CreateDirectory(path) 后,仍需调用 File.Create("C:\Temp\Bar\Foo\Test.txt") 来创建文件。 - sazr
这样做不起作用,因为它还会创建一个与文件名相同的目录。 - Bartosz Wójtowicz

17

5
给定一个路径,我们如何递归地创建所有必要的文件夹来创建该路径下的文件?
按照指定的路径创建所有目录和子目录。
Directory.CreateDirectory(path);

那么您可以创建一个文件。

2
路径不包括文件名 :) - Sameera R.
1
所有目录和子目录。错误:它最多只会创建一个目录和所有必需的子目录。 - Camilo Terevinto

4
你需要检查路径的两个部分(目录和文件名),如果它们不存在就创建它们。
使用File.ExistsDirectory.Exists来确定是否存在。如果目录不存在,Directory.CreateDirectory会为您创建整个路径,因此,如果目录不存在,只需调用一次,然后简单地创建文件即可。

对于Directory.CreateDirectory,您不需要查看哪个部分已存在。它将创建所需的所有目录(唯一需要确保的是目标目录尚不存在)。 - Gertjan
针对这种情况,我建议您删除答案的第一行,因为他不需要从根目录逐个检查每个部分,只需检查完整路径,并在不存在时创建它。 - Gertjan
@Gertjan - 答案已更新...希望现在符合您的标准;) - Oded
(我的意思不是要证明你错了或冒犯你,但初学者可以在答案中使用任何澄清) - Gertjan

2

备注:在路径中指定的所有目录都将被创建。...啊,太酷了!干杯 :) - Pure.Krome

1

假设您的程序集/可执行文件本身具有FileIO权限,这是不正确的。您的应用程序可能没有以管理员权限运行。重要的是要考虑代码访问安全性请求权限

示例代码:
FileIOPermission f2 = new FileIOPermission(FileIOPermissionAccess.Read, "C:\\test_r");
f2.AddPathList(FileIOPermissionAccess.Write | FileIOPermissionAccess.Read, "C:\\example\\out.txt");
try
{
    f2.Demand();
}
catch (SecurityException s)
{
    Console.WriteLine(s.Message);
}

了解.NET代码访问安全

“代码访问安全”在现实世界中有任何真正的用途吗?


2
@Pure.Krome: 尽管我的回答有点偏离问题,但在访问特权资源时,请考虑安全性和访问控制。并不是要取代或使你的问题变得复杂 :) - PRR

0
以下代码将会创建目录(如果不存在)并且复制文件。
// using System.IO;

// for ex. if you want to copy files from D:\A\ to D:\B\
foreach (var f in Directory.GetFiles(@"D:\A\", "*.*", SearchOption.AllDirectories))
{
    var fi =  new FileInfo(f);
    var di = new DirectoryInfo(fi.DirectoryName);

    // you can filter files here
    if (fi.Name.Contains("FILTER")
    {
        if (!Directory.Exists(di.FullName.Replace("A", "B"))
        {                       
            Directory.CreateDirectory(di.FullName.Replace("A", "B"));           
            File.Copy(fi.FullName, fi.FullName.Replace("A", "B"));
        }
    }
}

似乎提问者想要创建文件而不是复制它们。 - Thomas Fritz
@ThomasFritz,您说得对,但是我的回答中还有一些关于文件和文件夹操作的好信息,您觉得呢?我应该删除我的回答吗? - Mehdi Dehghani
我认为你不必删除你的答案本身:虽然它可能没有回答原始问题,但它放置在一些确实回答了该问题的答案下面。相反,你的答案作为一个介绍不同主题的引言,具体来说是如何复制文件,在StackOverflow答案中我不介意有一点多样性。如果你有时间,你可以调整你的答案措辞,使其不像是最完整的答案,我认为这是夸大其词的表现。 - Thomas Fritz

0

你想使用 Directory.CreateDirectory() 函数。

这里是一个我使用的类(已转换为 C#),如果你传入一个源目录和一个目标目录,它将复制该目录下所有文件和子文件夹到你的目标目录:

using System.IO;

public class copyTemplateFiles
{


public static bool Copy(string Source, string destination)
{

    try {

        string[] Files = null;

        if (destination[destination.Length - 1] != Path.DirectorySeparatorChar) {
            destination += Path.DirectorySeparatorChar;
        }

        if (!Directory.Exists(destination)) {
            Directory.CreateDirectory(destination);
        }

        Files = Directory.GetFileSystemEntries(Source);
        foreach (string Element in Files) {
            // Sub directories
            if (Directory.Exists(Element)) {
                copyDirectory(Element, destination + Path.GetFileName(Element));
            } else {
                // Files in directory
                File.Copy(Element, destination + Path.GetFileName(Element), true);
            }
        }

    } catch (Exception ex) {
        return false;
    }

    return true;

}



private static void copyDirectory(string Source, string destination)
{
    string[] Files = null;

    if (destination[destination.Length - 1] != Path.DirectorySeparatorChar) {
        destination += Path.DirectorySeparatorChar;
    }

    if (!Directory.Exists(destination)) {
        Directory.CreateDirectory(destination);
    }

    Files = Directory.GetFileSystemEntries(Source);
    foreach (string Element in Files) {
        // Sub directories
        if (Directory.Exists(Element)) {
            copyDirectory(Element, destination + Path.GetFileName(Element));
        } else {
            // Files in directory
            File.Copy(Element, destination + Path.GetFileName(Element), true);
        }
    }

}

}


3
我应该将其降级,因为有这一行代码:using Microsoft.VisualBasic; 真是太邪恶了!! - Pure.Krome
2
为什么Microsoft.VisualBasic很恶心?它只是在.NET框架中像其他程序集一样存在啊。 - Oliver
2
我猜测是因为你不必要地导入了一个完全不同语言的命名空间..? - Markive

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接