1. Вступ
Якщо статичні класи, такі як File і Directory, — це як універсальний швейцарський ніж: завжди під рукою, швидко розв’язують завдання, але без прив’язки до конкретного об’єкта, то FileInfo й DirectoryInfo — це вже персоналізований інструмент: він створюється для конкретного файлу або каталогу, «знає» про них чимало й дає змогу працювати зручніше та гнучкіше, особливо під час багаторазових операцій із тим самим об’єктом.
Екземплярні класи зберігають деталі про конкретний об’єкт файлової системи, причому після першого зчитування властивостей не завжди потрібно знову звертатися до файлової системи по інформацію (якщо лише дані не застаріли).
- FileInfo — для роботи з конкретним файлом.
- DirectoryInfo — для роботи з конкретним каталогом (папкою).
Вони містять властивості й методи, які дають змогу отримувати детальну інформацію (розмір, дату створення, розширення, доступні атрибути) і виконувати над файлом/каталогом різні дії: копіювати, видаляти, переміщувати тощо.
Як влаштовані FileInfo й DirectoryInfo
Обидва класи — нащадки спільного абстрактного класу FileSystemInfo, який дає змогу писати код, що працює з файлами й каталогами одночасно.
System.Object
|
System.MarshalByRefObject
|
System.IO.FileSystemInfo (абстрактний клас)
| |
FileInfo DirectoryInfo
Коли використовувати екземплярні класи?
- Якщо потрібно багато інформації про один файл або каталог (розмір, дата модифікації, розширення, атрибути тощо), і ці дані використовуються не один раз.
- Якщо ви хочете перебрати всі файли та підкаталоги в каталозі й працювати з кожним об’єктом як із «живим» екземпляром.
- Для оптимізації, коли важливо уникати зайвих звернень до файлової системи (кешування інформації).
- Для більш об’єктно-орієнтованого коду (резервні копії, медіатека, файловий менеджер тощо).
Як створити екземпляр FileInfo або DirectoryInfo
using System.IO;
// Створення об’єкта FileInfo для наявного (або й неіснуючого!) файлу:
var fileInfo = new FileInfo("notes.txt");
// Створення об’єкта DirectoryInfo для каталогу:
var dirInfo = new DirectoryInfo(@"C:\Projects");
// Можна використовувати відносні або абсолютні шляхи!
Важливий момент: створення об’єкта FileInfo або DirectoryInfo НЕ створює файл/каталог у файловій системі! Це лише опис (зв’язок за посиланням).
2. Робота з FileInfo
Розберімо основні властивості та методи цього класу. Ось шпаргалка:
| Властивість/метод | Що повертає? | Приклад використання |
|---|---|---|
|
Імʼя файлу | |
|
Повний шлях | |
|
Розмір файлу в байтах | |
|
Батьківський каталог (DirectoryInfo) | |
|
Файл існує? | |
|
Розширення файлу (.txt) | |
|
Дата створення | |
|
Дата останньої зміни | |
|
Лише для читання? | |
| Методи | ||
|
Копіювати файл | |
|
Видалити файл | |
|
Перемістити файл | |
|
Відкрити потік для читання | |
|
Відкрити потік для запису | |
Приклад: інформація про файл
Додамо невеликий модуль, який отримує детальну інформацію про файл, використовуючи FileInfo.
Console.WriteLine("Введіть імʼя файлу:");
string fileName = Console.ReadLine();
var file = new FileInfo(fileName);
if (file.Exists)
{
Console.WriteLine($"Імʼя файлу: {file.Name}");
Console.WriteLine($"Шлях: {file.FullName}");
Console.WriteLine($"Розмір: {file.Length} байт");
Console.WriteLine($"Розширення: {file.Extension}");
Console.WriteLine($"Дата створення: {file.CreationTime}");
Console.WriteLine($"Остання зміна: {file.LastWriteTime}");
// Додатково: показати батьківський каталог
Console.WriteLine($"Батьківський каталог: {file.DirectoryName}");
}
else
{
Console.WriteLine("Файл не знайдено.");
}
Зверніть увагу: ми не читаємо вміст файлу, а просто отримуємо метаінформацію.
Практика: копіювання та видалення файлу
// ... Усередині основного методу після успішного виводу відомостей про файл:
Console.WriteLine("Введіть шлях для копії файлу:");
string copyPath = Console.ReadLine();
try
{
file.CopyTo(copyPath);
Console.WriteLine($"Файл успішно скопійовано в {copyPath}");
}
catch (IOException ex)
{
Console.WriteLine($"Не вдалося скопіювати файл: {ex.Message}");
}
// Тепер видалимо копію
Console.WriteLine("Видалити копію файлу? (y/n):");
if (Console.ReadLine().Trim().ToLower() == "y")
{
var copyFile = new FileInfo(copyPath);
if (copyFile.Exists)
{
copyFile.Delete();
Console.WriteLine("Копію видалено.");
}
}
3. Робота з DirectoryInfo
Погляньмо, що вміє DirectoryInfo:
| Властивість/метод | Що повертає? | Приклад використання |
|---|---|---|
|
Імʼя каталогу | |
|
Повний шлях | |
|
Батьківський каталог (DirectoryInfo) | |
|
Каталог існує? | |
|
Дата створення | |
|
Дата зміни | |
| Методи | ||
|
Створити каталог | |
|
Видалити каталог | |
|
Масив файлів (масив FileInfo) | |
|
Масив підкаталогів (масив DirectoryInfo) | |
|
Перебирання файлів (повертає IEnumerable<FileInfo>, відкладене виконання) | |
|
Перемістити каталог | |
Приклад: перебирання файлів і каталогів
Console.WriteLine("Введіть шлях до каталогу:");
string path = Console.ReadLine();
var dir = new DirectoryInfo(path);
if (!dir.Exists)
{
Console.WriteLine("Каталог не знайдено!");
return;
}
Console.WriteLine("\n--- Файли ---");
foreach (var file in dir.GetFiles())
{
Console.WriteLine($"{file.Name} ({file.Length} байт)");
}
Console.WriteLine("\n--- Підкаталоги ---");
foreach (var subDir in dir.GetDirectories())
{
Console.WriteLine(subDir.Name);
}
4. Корисні нюанси
Статичні методи проти екземплярних класів
Коли варто використовувати який підхід? Якщо ви робите швидку «одноразову» дію — наприклад, File.Exists(path) або File.ReadAllText(path), — статичні методи будуть найзручнішими. Вони простіші й трохи швидші завдяки мінімальним накладним витратам.
Якщо ж ви хочете отримати багато інформації про файл або каталог, виконувати над цим об’єктом повторні операції або просто пишете код в ООП-стилі, — краще використовувати екземпляри FileInfo й DirectoryInfo.
Цікаво, що обидва підходи «під капотом» використовують схожі низькорівневі системні виклики. Але екземплярні класи кешують деякі властивості (розмір, дати, атрибути), мінімізуючи кількість звернень до файлової системи — особливо під час перебирання великої кількості файлів.
Трохи про роботу з датою й часом
Властивості CreationTime, LastWriteTime, LastAccessTime повертають значення типу DateTime.
Console.WriteLine($"Файл створено: {file.CreationTime:yyyy-MM-dd HH:mm:ss}");
Console.WriteLine($"Остання зміна: {file.LastWriteTime:yyyy-MM-dd HH:mm:ss}");
Якщо файл або каталог було змінено на диску після того, як ви отримали об’єкт FileInfo або DirectoryInfo, кешована інформація може застаріти. Щоб оновити її, викличте file.Refresh().
Поради та практичні зауваження
- Екземплярні класи зручні, коли ви будуєте обгортку над файловою системою: резервні копії, медіатека, індексатор.
- Чудово працюють разом із LINQ: можна відфільтрувати за розміром, датою або розширенням і виконати операції над обраними об’єктами.
- Для масових операцій краще EnumerateFiles() і EnumerateDirectories(), ніж GetFiles()/GetDirectories(), — ліниве перебирання заощаджує памʼять і пришвидшує старт обробки.
Порівняння статичного та екземплярного підходу
| Статичні методи | Екземплярні класи | |
|---|---|---|
| Синтаксис | |
|
| Кешування | Ні | Так |
| Багато інформації | Потрібно викликати багато методів | Є в об’єкті |
| ООП-стиль | Ні | Так |
| Масові операції | Незручно | Зручно |
| Робота з потоками | Є | Є |
Оновлення інформації та об’єктів
Об’єкти FileInfo/DirectoryInfo кешують значення після першого звернення до властивостей. Якщо об’єкт (файл або каталог) було змінено на диску після створення екземпляра, щоб оновити інформацію, викличте метод .Refresh().
var file = new FileInfo("notes.txt");
long oldSize = file.Length;
// У цей час хтось (або ви самі) змінює файл поза програмою
file.Refresh();
long newSize = file.Length;
Таке трапляється нечасто, але якщо ваша програма спостерігає за файловою системою — механізм важливий.
5. Типові помилки під час роботи з екземплярними класами
Омана: якщо створено об’єкт new FileInfo("file.txt"), то файл уже існує. Насправді це не так — файл з’являється тільки після явного запису або виклику Create().
Спроба отримати властивості файлу, якого не існує: деякі властивості повернуть значення за замовчуванням (наприклад, розмір 0), але спроба відкрити потік читання спричинить виняток.
Із каталогами — так само: створення DirectoryInfo не гарантує, що каталог є на диску до виклику Create() або його фактичної появи.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ