C# 创建文件,递归创建目录
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10941657/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
creating files, recursively creating directories
提问by MxLDevs
I was reading some file IO tutorials for C# and have managed to write out some files, but what if the path I'm given contains directories?
我正在阅读 C# 的一些文件 IO 教程并设法写出一些文件,但是如果我给出的路径包含目录怎么办?
For example, I want to create the file called data/my_fileexcept datafolder doesn't exist.
例如,我想创建名为data/my_fileexceptdata文件夹不存在的文件。
The line,
线,
BinaryWriter outFile = new BinaryWriter(File.OpenWrite(path));
where pathis the above string, crashes with the message that part of the path doesn't exist, which means C# isn't creating them as required.
path上面的字符串在哪里,崩溃并显示路径的一部分不存在的消息,这意味着 C# 没有按要求创建它们。
I would like C# to handle all of the messy directory creation and checking for me instead of me having to parse the path and create all of the necessary directories. Is this possible? Otherwise, is there a snippet of code that I can just copy over into my project which will handle anything I might be overlooking (since I don't know much about file management).
我希望 C# 处理所有杂乱的目录创建和检查我,而不是我必须解析路径并创建所有必要的目录。这可能吗?否则,是否有一段代码可以复制到我的项目中,它可以处理我可能忽略的任何事情(因为我对文件管理知之甚少)。
采纳答案by Eric J.
System.IO.Directory.CreateDirectory()will create all directories and subdirectories in a specified path, should they not already exist.
System.IO.Directory.CreateDirectory()将在指定路径中创建所有目录和子目录,如果它们不存在的话。
You can call it, passing the path, to ensure the folder structure is created prior to writing your file.
您可以调用它,传递路径,以确保在写入文件之前创建文件夹结构。
回答by Eternal21
While System.IO.Directory.CreateDirectory() will indeed create directories for you recursively, I came across a situation where I had to come up with my own method. Basically System.IO doesn't support paths over 260 characters, which forced me to use Delimon.Win32.IO library, which works with long paths, but doesn't create directories recursively.
虽然 System.IO.Directory.CreateDirectory() 确实会递归地为你创建目录,但我遇到了一种情况,我不得不想出我自己的方法。基本上 System.IO 不支持超过 260 个字符的路径,这迫使我使用 Delimon.Win32.IO 库,它适用于长路径,但不会递归创建目录。
Here's the code I used for creating directories recursively:
这是我用于递归创建目录的代码:
void CreateDirectoryRecursively(string path)
{
string[] pathParts = path.Split('\');
for (int i = 0; i < pathParts.Length; i++)
{
if (i > 0)
pathParts[i] = Path.Combine(pathParts[i - 1], pathParts[i]);
if (!Directory.Exists(pathParts[i]))
Directory.CreateDirectory(pathParts[i]);
}
}
回答by williambq
So, the above didn't work super well for me for basic directory creation. I modified this a bit to handle common cases for drive letters and a path with a file resource on the end.
因此,对于基本目录创建,上述内容对我来说效果不佳。我对此做了一些修改,以处理驱动器号和末尾带有文件资源的路径的常见情况。
public bool CreateDirectoryRecursively(string path)
{
try
{
string[] pathParts = path.Split('\');
for (var i = 0; i < pathParts.Length; i++)
{
// Correct part for drive letters
if (i == 0 && pathParts[i].Contains(":"))
{
pathParts[i] = pathParts[i] + "\";
} // Do not try to create last part if it has a period (is probably the file name)
else if (i == pathParts.Length-1 && pathParts[i].Contains("."))
{
return true;
}
if (i > 0) {
pathParts[i] = Path.Combine(pathParts[i - 1], pathParts[i]);
}
if (!Directory.Exists(pathParts[i]))
{
Directory.CreateDirectory(pathParts[i]);
}
}
return true;
}
catch (Exception ex)
{
var recipients = _emailErrorDefaultRecipients;
var subject = "ERROR: Failed To Create Directories in " + this.ToString() + " path: " + path;
var errorMessage = Error.BuildErrorMessage(ex, subject);
Email.SendMail(recipients, subject, errorMessage);
Console.WriteLine(errorMessage);
return false;
}
}
回答by ephraim
Previous answers didn't handle Network paths. Attached code which also handles that.
以前的答案没有处理网络路径。附加的代码也处理这个问题。
/// <summary>
/// tests (and creates missing) directories in path containing many
subDirectories which might not exist.
/// </summary>
/// <param name="FN"></param>
public static string VerifyPath(string FN, out bool AllOK)
{
AllOK = true;
var dir = FolderUtils.GetParent(FN);
if (!Directory.Exists(dir))//todo - move to folderUtils.TestFullDirectory
{
const char DIR = '\';
//string dirDel = "" + DIR;
string[] subDirs = FN.Split(DIR);
string dir2Check = "";
int startFrom = 1;//skip "c:\"
FN = CleanPathFromDoubleSlashes(FN);
if (FN.StartsWith("" + DIR + DIR))//netPath
startFrom = 3;//FN.IndexOf(DIR, 2);//skip first two slashes..
for (int i = 0; i < startFrom; i++)
dir2Check += subDirs[i] + DIR;//fill in begining
for (int i = startFrom; i < subDirs.Length - 1; i++)//-1 for the file name..
{
dir2Check += subDirs[i] + DIR;
if (!Directory.Exists(dir2Check))
try
{
Directory.CreateDirectory(dir2Check);
}
catch { AllOK = false; }
}
}
if (File.Exists(FN))
FN = FolderUtils.getFirstNonExistingPath(FN);
if (FN.EndsWith("\") && !Directory.Exists(FN))
try { Directory.CreateDirectory(FN); }
catch
{
HLogger.HandleMesssage("couldn't create dir:" + FN, TypeOfExceptions.error, PartsOfSW.FileStructure);
AllOK = false;
}
return FN;
}
And the "CleanDoubleSlashes function":
以及“CleanDoubleSlashes 函数”:
public static string CleanPathFromDoubleSlashes(string basePath)
{
if (string.IsNullOrEmpty(basePath) || basePath.Length < 2)//don't clean first \ of LAN address
return basePath;
for (int i = basePath.Length - 1; i > 1; i--)
{
if ((basePath[i] == '\' && basePath[i - 1] == '\') || (basePath[i] == '/' && basePath[i - 1] == '/'))
{
basePath = basePath.Remove(i, 1);//Substring(0, i - 2) + basePath.Substring(i, basePath.Length - 1 - i);
}
}
return basePath;
}
回答by H7O
here is how I usually do it
这是我通常的做法
Directory.CreateDirectory(Path.GetDirectoryName(filePath));
^ this should take care of ensuring all necessary folders (regardless if some of them already exist) that precedes your file are created. E.g. if you pass it "c:/a/b/c/data/my file.txt", it should ensure "c:/a/b/c/data" path is created.
^ 这应该确保在您的文件之前创建所有必需的文件夹(无论其中一些文件夹是否已经存在)。例如,如果你传递它“c:/a/b/c/data/my file.txt”,它应该确保“c:/a/b/c/data”路径被创建。

