Ответ 1
System.IO.Directory.CreateDirectory() создаст все каталоги и подкаталоги по указанному пути, если они еще не существуют.
Вы можете вызвать его, передав путь, чтобы убедиться, что структура папки создана до записи вашего файла.
Я читал несколько учебных руководств по IO для С# и мне удалось записать некоторые файлы, но что, если заданный путь содержит каталоги?
Например, я хочу создать файл с именем data/my_file
, кроме data
папка не существует.
Линия,
BinaryWriter outFile = new BinaryWriter(File.OpenWrite(path));
где path
- указанная выше строка, сбой сообщения с сообщением о том, что часть пути не существует, что означает, что С# не создает их по мере необходимости.
Я бы хотел, чтобы С# обрабатывал все беспорядочное создание каталога и проверял меня вместо того, чтобы я разбирался в пути и создавал все необходимые каталоги. Это возможно? В противном случае есть фрагмент кода, который я могу просто скопировать в свой проект, который будет обрабатывать все, что я могу игнорировать (поскольку я мало знаю о управлении файлами).
System.IO.Directory.CreateDirectory() создаст все каталоги и подкаталоги по указанному пути, если они еще не существуют.
Вы можете вызвать его, передав путь, чтобы убедиться, что структура папки создана до записи вашего файла.
В то время как System.IO.Directory.CreateDirectory() действительно создаст каталоги для вас рекурсивно, я столкнулся с ситуацией, когда мне пришлось придумать свой собственный метод. В основном System.IO не поддерживает пути более 260 символов, что заставило меня использовать библиотеку Delimon.Win32.IO, которая работает с длинными путями, но не рекурсивно создает каталоги.
Здесь код, который я использовал для рекурсивного создания каталогов:
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]);
}
}
Итак, вышеописанное не очень хорошо работает для меня для создания базового каталога. Я немного изменил это, чтобы обрабатывать обычные случаи для букв дисков и путь с файловым ресурсом в конце.
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;
}
}
Предыдущие ответы не обрабатывали сетевые пути. Прикрепленный код, который также обрабатывает это.
/// <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;
}
И функция "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;
}
вот как я обычно это делаю
Directory.CreateDirectory(Path.GetDirectoryName(filePath));
^ это должно обеспечить создание всех необходимых папок (независимо от того, существуют ли некоторые из них), предшествующих вашему файлу. Например, если вы передадите ему "c: /a/b/c/data/my file.txt", это должно обеспечить создание пути "c: /a/b/c/data".