Работа с каталогами


Для работы с каталогами в пространстве имен System.IO предназначены сразу два класса: Directory и DirectoryInfo.

Класс Directory
Статический класс Directory предоставляет ряд методов для управления каталогами. Некоторые из этих методов:

CreateDirectory(path): создает каталог по указанному пути path

Delete(path): удаляет каталог по указанному пути path

Exists(path): определяет, существует ли каталог по указанному пути path. Если существует, возвращается true, если не существует, то false

GetCurrentDirectory(): получает путь к текущей папке

GetDirectories(path): получает список подкаталогов в каталоге path

GetFiles(path): получает список файлов в каталоге path

GetFileSystemEntries(path): получает список подкаталогов и файлов в каталоге path

Move(sourceDirName, destDirName): перемещает каталог

GetParent(path): получение родительского каталога

GetLastWriteTime(path): возвращает время последнего изменения каталога

GetLastAccessTime(path): возвращает время последнего обращения к каталогу

GetCreationTime(path): возвращает время создания каталога

Класс DirectoryInfo
Данный класс предоставляет функциональность для создания, удаления, перемещения и других операций с каталогами. Во многом он похож на Directory, но не является статическим.

Для создания объекта класса DirectoryInfo применяется конструктор, который в качестве параметра принимает путь к каталогу:

public DirectoryInfo (string path);
Основные методы класса DirectoryInfo:

Create(): создает каталог

CreateSubdirectory(path): создает подкаталог по указанному пути path

Delete(): удаляет каталог

GetDirectories(): получает список подкаталогов папки в виде массива DirectoryInfo

GetFiles(): получает список файлов в папке в виде массива FileInfo

MoveTo(destDirName): перемещает каталог

Основные свойства класса DirectoryInfo:

CreationTime: представляет время создания каталога

LastAccessTime: представляет время последнего доступа к каталогу

LastWriteTime: представляет время последнего изменения каталога

Exists: определяет, существует ли каталог

Parent: получение родительского каталога

Root: получение корневого каталога

Name: имя каталога

FullName: полный путь к каталогу

Directory или DirectoryInfo
Как видно из функционала, оба класса предоставляют похожие возможности. Когда же и что использовать? Если надо совершить одну-две операции с одним каталогом, то проще использовать класс Directory. Если необходимо выполнить последовательность операций с одним и тем же каталогом, то лучше воспользоваться классом DirectoryInfo. Почему? Дело в том, что методы класса Directory выполняют дополнительные проверки безопасности. А для класса DirectoryInfo такие проверки не всегда обязательны.

Посмотрим на примерах применение этих классов

Получение списка файлов и подкаталогов

string dirName = "C:\\";
// если папка существует
if (Directory.Exists(dirName))
{
Console.WriteLine("Подкаталоги:");
string[] dirs = Directory.GetDirectories(dirName);
foreach (string s in dirs)
{
Console.WriteLine(s);
}
Console.WriteLine();
Console.WriteLine("Файлы:");
string[] files = Directory.GetFiles(dirName);
foreach (string s in files)
{
Console.WriteLine(s);
}
}
Обратите внимание на использование слешей в именах файлов. Либо мы используем двойной слеш: "C:\\", либо одинарный, но тогда перед всем путем ставим знак @: @"C:\Program Files"

Аналогичный пример с DirectoryInfo:

string dirName = "C:\";

var directory = new DirectoryInfo(dirName);

if (directory.Exists)
{
Console.WriteLine("Подкаталоги:");
DirectoryInfo[] dirs = directory.GetDirectories();
foreach (DirectoryInfo dir in dirs)
{
Console.WriteLine(dir.FullName);
}
Console.WriteLine();
Console.WriteLine("Файлы:");
FileInfo[] files = directory.GetFiles();
foreach (FileInfo file in files)
{
Console.WriteLine(file.FullName);
}
}
Фильтрация папок и файлов
Методы получения папок и файлов позволяют выполнять фильтрацию. В качестве фильтра в эти методы передается шаблон, который может содержать два плейсхолдера: * или символ-звездочка (соответствует любому количеству символов) и ? или вопросительный знак (соответствует одному символу)

Например, найдем все папки, которые начинаются на "books":

// класс Directory
string[] dirs = Directory.GetDirectories(dirName, "books*.");

// класс DirectoryInfo
var directory = new DirectoryInfo(dirName);
DirectoryInfo[] dirs = directory.GetDirectories("books*.");
Или получим все файлы с расширением ".exe":

// класс Directory
string[] files = Directory.GetFiles(dirName, "*.exe");

// класс DirectoryInfo
var directory = new DirectoryInfo(dirName);
FileInfo[] files = directory.GetFiles("*.exe");
Создание каталога
Класс DirectoryInfo

string path = @"C:\SomeDir";
string subpath = @"program\avalon";
DirectoryInfo dirInfo = new DirectoryInfo(path);
if (!dirInfo.Exists)
{
dirInfo.Create();
}
dirInfo.CreateSubdirectory(subpath);
Вначале проверяем, а нету ли такой директории, так как если она существует, то ее создать будет нельзя, и приложение выбросит ошибку. В итоге у нас получится следующий путь: "C:\SomeDir\program\avalon"

Аналогичный пример с классом Directory:

string path = @"C:\SomeDir";
string subpath = @"program\avalon";
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
Directory.CreateDirectory($"{path}/{subpath}");
Получение информации о каталоге

string dirName = "C:\\Program Files";

DirectoryInfo dirInfo = new DirectoryInfo(dirName);

Console.WriteLine($"Название каталога: {dirInfo.Name}");
Console.WriteLine($"Полное название каталога: {dirInfo.FullName}");
Console.WriteLine($"Время создания каталога: {dirInfo.CreationTime}");
Console.WriteLine($"Корневой каталог: {dirInfo.Root}");
Удаление каталога
Если мы просто применим метод Delete к непустой папке, в которой есть какие-нибудь файлы или подкаталоги, то приложение нам выбросит ошибку. Поэтому нам надо передать в метод Delete дополнительный параметр булевого типа, который укажет, что папку надо удалять со всем содержимым. Кроме того, перед удалением следует проверить наличие удаляемой папки, иначе приложение выбросит исключение:

string dirName = @"C:\SomeDir";

DirectoryInfo dirInfo = new DirectoryInfo(dirName);
if (dirInfo.Exists)
{
dirInfo.Delete(true);
Console.WriteLine("Каталог удален");
}
else
{
Console.WriteLine("Каталог не существует");
}
Или так:

string dirName = @"C:\SomeDir";
if (Directory.Exists(dirName))
{
Directory.Delete(dirName, true);
Console.WriteLine("Каталог удален");
}
else
{
Console.WriteLine("Каталог не существует");
}
Перемещение каталога
При перемещении надо учитывать, что новый каталог, в который мы хотим перемесить все содержимое старого каталога, не должен существовать.

string oldPath = @"C:\SomeFolder";
string newPath = @"C:\SomeDir";
DirectoryInfo dirInfo = new DirectoryInfo(oldPath);
if (dirInfo.Exists && !Directory.Exists(newPath))
{
dirInfo.MoveTo(newPath);
// или так
// Directory.Move(oldPath, newPath);
}
Перемещение каталога в рамках одной папки (как в примере выше) фактически аналогично переименованию папки