1. Вступ
Працювати безпосередньо з потоками (StreamReader, StreamWriter, FileStream) дуже корисно, особливо коли треба контролювати процес читання/запису на низькому рівні: наприклад, записувати блоки «потроху» або обробляти великі файли частинами.
А в реальному житті нерідко потрібно просто з’ясувати: «чи існує цей файл?», «скопіювати файл з місця на місце», «видалити файл», «отримати список усіх .txt-файлів у папці» тощо. Для таких завдань Microsoft створила два універсальні інструменти: статичні класи File і Directory. Статичні — отже, екземпляр створювати не потрібно: одразу викликаєте потрібний метод за імʼям класу.
Життєва аналогія
Якщо потоки — це ви з олівцем, який акуратно пише кожну літеру на аркуші паперу, то File і Directory — це ваш стіл із шухлядами: ви можете «миттєво» відкрити шухляду (Directory), дістати з неї папірець (File.ReadAllText), викинути папірець (File.Delete) або навіть витягнути цілу шухляду й відправити її в інший кінець кімнати (Directory.Move). Прості завдання — прості методи.
2. Клас File: що це і навіщо потрібен
Клас File має дуже зручний набір статичних методів для всіх популярних операцій із файлами.
Найчастіше вживані методи
| Метод | Опис |
|---|---|
|
Перевіряє, чи існує файл за вказаним шляхом. |
|
Зчитує весь файл як текст. |
|
Зчитує всі рядки файлу в масив. |
|
Перезаписує файл указаним текстом. |
|
Дописує текст у кінець файлу. |
|
Копіює файл. |
|
Видаляє файл. |
|
Переміщує або перейменовує файл. |
|
Відкриває потік для складних операцій. |
Швидкий приклад: перевіряємо файл і читаємо його
string filePath = "data.txt";
if (File.Exists(filePath))
{
string content = File.ReadAllText(filePath);
Console.WriteLine("Вміст файлу:");
Console.WriteLine(content);
}
else
{
Console.WriteLine("Файл не знайдено!");
}
Бачите? Жодного ручного керування потоками для простого випадку!
3. Клас Directory: керування папками без зайвого клопоту
Якщо File — про окремі файли, то Directory — про папки (каталоги).
Основні завдання
| Метод | Опис |
|---|---|
|
Перевіряє, чи існує папка. |
|
Створює папку (або цілий шлях із усіма проміжними папками). |
|
Видаляє папку (можна разом із підпапками). |
|
Отримує список файлів у папці. |
|
Отримує список підпапок. |
|
Переміщує або перейменовує папку. |
|
Отримує поточну робочу папку застосунку. |
Приклад: створюємо папку й зберігаємо туди файл
string dirPath = "Results";
if (!Directory.Exists(dirPath))
{
Directory.CreateDirectory(dirPath);
Console.WriteLine("Папку 'Results' створено.");
}
string filePath = Path.Combine(dirPath, "summary.txt");
File.WriteAllText(filePath, "Підсумкові дані: ...");
Console.WriteLine($"Файл {filePath} записано.");
4. Типові сценарії використання File і Directory
Базові методи здаватимуться нудними, якщо не бачити їх у дії! Подивімося, як використовувати ці класи для розв’язання реальних завдань, і водночас продовжимо розвивати наш умовний застосунок (давайте уявімо, що ми створюємо просту систему для ведення списку справ — todo-list, а результати зберігаємо у файлах).
Збереження даних у файл (заміна старого файлу)
// Зберігаємо список завдань у файл
string[] todos = { "Купити хліб", "Подзвонити лікарю", "Зробити домашнє завдання з C#" };
string filePath = "todo.txt";
File.WriteAllLines(filePath, todos);
Console.WriteLine("Список справ збережено.");
Завантаження даних із файлу
// Завантажуємо завдання, якщо файл є
if (File.Exists(filePath))
{
string[] loadedTodos = File.ReadAllLines(filePath);
Console.WriteLine("Ваш список справ:");
foreach (var task in loadedTodos)
{
Console.WriteLine("- " + task);
}
}
else
{
Console.WriteLine("Поки у вас немає списку справ.");
}
Додавання нового завдання (без перезапису файлу)
string newTask = "Погуляти з собакою";
File.AppendAllText(filePath, newTask + Environment.NewLine);
Console.WriteLine("Завдання додано!");
Копіювання та резервне копіювання файлу
string backupPath = "todo_backup.txt";
File.Copy(filePath, backupPath, overwrite: true);
Console.WriteLine("Резервну копію списку справ створено.");
Переміщення (або перейменування) файлу
string archivePath = "todo_archive.txt";
File.Move(filePath, archivePath);
Console.WriteLine("Список справ заархівовано (перейменовано).");
Видалення файлу
if (File.Exists(archivePath))
{
File.Delete(archivePath);
Console.WriteLine("Архів видалено — звільнено місце!");
}
5. Робота з папками: приклади
Створення ієрархії папок
string path = Path.Combine("Reports", "2024", "June");
Directory.CreateDirectory(path);
Console.WriteLine($"Папку {path} створено (включно з проміжними папками).");
Отримання списку файлів і папок
string dirPath = "Reports";
if (Directory.Exists(dirPath))
{
string[] files = Directory.GetFiles(dirPath);
Console.WriteLine("Файли в папці:");
foreach (var file in files)
{
Console.WriteLine(file);
}
string[] subDirs = Directory.GetDirectories(dirPath);
Console.WriteLine("Підпапки:");
foreach (var dir in subDirs)
{
Console.WriteLine(dir);
}
}
Фільтрація файлів за маскою (лише txt)
string[] txtFiles = Directory.GetFiles(dirPath, "*.txt");
Console.WriteLine("Лише .txt-файли:");
foreach (var file in txtFiles)
{
Console.WriteLine(file);
}
Рекурсивний обхід (файли в усіх підпапках)
string[] allFiles = Directory.GetFiles(dirPath, "*.*", SearchOption.AllDirectories);
Console.WriteLine("Файли в усіх вкладених папках:");
foreach (var file in allFiles)
{
Console.WriteLine(file);
}
Переміщення та видалення папок
string from = "OldReports";
string to = "Archive/OldReports";
if (Directory.Exists(from))
{
Directory.Move(from, to);
Console.WriteLine($"Папку {from} переміщено до {to}");
}
if (Directory.Exists(to))
{
Directory.Delete(to, recursive: true); // true: видалити все всередині
Console.WriteLine($"Папку {to} видалено (разом із усім вмістом).");
}
6. Корисні нюанси
Інтеграція зі шляхами: клас Path
Під час роботи з файлами та папками часто доводиться складати повні шляхи, об’єднувати імена папок і файлів, розбирати розширення, перевіряти коректність символів. Для цього використовують допоміжний клас Path.
Приклади
string folder = "Results";
string filename = "week1.txt";
string fullPath = Path.Combine(folder, filename); // безпечне об’єднання!
Console.WriteLine(fullPath); // "Results/week1.txt" (або "\" на Windows)
- Отримати розширення файлу: Path.GetExtension(fullPath)
- Отримати імʼя файлу без шляху: Path.GetFileName(fullPath)
Використовуйте Path.Combine замість конкатенації рядків — так безпечніше для кросплатформених застосунків.
Методи «все й одразу» проти потокового варіанту
Багато методів File і Directory (наприклад, File.ReadAllText, File.WriteAllText, Directory.GetFiles) виконують всю роботу «повністю»: зчитують/записують/отримують список файлів за одну операцію. Це дуже зручно, але не підходить для дуже великих файлів або папок, де може закінчитися памʼять. Якщо працюєте з гігабайтами — переходьте на потокові класи (StreamReader, StreamWriter, FileStream тощо) або обробляйте файли частинами.
Коли використовувати File/Directory, а коли — класи потоків
| Ситуація | Що використовувати |
|---|---|
| Потрібно перевірити, чи існує файл/папка | |
| Прочитати/записати весь невеликий файл | |
| Додати текст у кінець файлу | |
| Отримати список файлів у папці | |
| Копіювати, видалити, перемістити файл | |
| Копіювати/видалити цілу папку | Directory.Delete/Move/Copy (Copy — зі сторонньою бібліотекою) |
| Обробляти дуже великі файли частинами | Класи потоків (StreamReader, FileStream) |
Практичне значення та реальне застосування
- Швидке завантаження/збереження конфігурацій, налаштувань, JSON/XML-файлів.
- Системи логування (запис логів на диск).
- Прості утиліти резервного копіювання (бекапи) та міграції даних.
- Сканування папок із мультимедіа, фотографіями, документами.
- Користувацькі сценарії: завантаження шаблонів, експорт/імпорт, генерація звітів тощо.
Практичні завдання на співбесідах теж часто вимагають використовувати саме ці класи: «Реалізуйте функцію, яка рахує сумарний розмір усіх .txt-файлів у папці», «Зробіть резервну копію файлів в окрему папку» тощо.
Візуальна шпаргалка: коли який метод використовувати
graph TD
A[Що ви хочете зробити?]
A -->|Перевірити існування| B[File.Exists або Directory.Exists]
A -->|Прочитати/записати файл повністю| C[File.ReadAllText/WriteAllText]
A -->|Додати дані у файл| D[File.AppendAllText]
A -->|Робота з папками| E[Directory.CreateDirectory, GetFiles, GetDirectories]
A -->|Копіювати/видалити/перемістити файл| F[File.Copy/Delete/Move]
A -->|Копіювати/видалити папку повністю| G[Directory.Delete/Move]
7. Особливості та типові помилки
Перевірка на існування і «стан гонки». Навіть якщо ви перевірили, що файл/папка існує, між цією перевіркою й реальною операцією інший процес може все змінити. Тому завжди використовуйте try-catch, навіть якщо вже перевірили наявність!
Права доступу. Якщо застосунку бракує прав на читання/запис/видалення, методи спричинять UnauthorizedAccessException.
Надто довгий шлях. Максимальна довжина шляху (зазвичай 260 символів на старих Windows; у .NET 9 обмеження мʼякші, але все одно остерігайтеся).
Обробка помилок. Такі методи, як File.ReadAllText або Directory.GetFiles, помилок не пробачають: якщо файлу/папки немає — одразу виняток. Обгорніть виклики в try-catch або попередньо перевірте наявність.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ