JavaRush /Курси /C# SELF /Статичні класи File...

Статичні класи File і Directory

C# SELF
Рівень 39 , Лекція 0
Відкрита

1. Вступ

Працювати безпосередньо з потоками (StreamReader, StreamWriter, FileStream) дуже корисно, особливо коли треба контролювати процес читання/запису на низькому рівні: наприклад, записувати блоки «потроху» або обробляти великі файли частинами.

А в реальному житті нерідко потрібно просто з’ясувати: «чи існує цей файл?», «скопіювати файл з місця на місце», «видалити файл», «отримати список усіх .txt-файлів у папці» тощо. Для таких завдань Microsoft створила два універсальні інструменти: статичні класи File і Directory. Статичні — отже, екземпляр створювати не потрібно: одразу викликаєте потрібний метод за імʼям класу.

Життєва аналогія

Якщо потоки — це ви з олівцем, який акуратно пише кожну літеру на аркуші паперу, то File і Directory — це ваш стіл із шухлядами: ви можете «миттєво» відкрити шухляду (Directory), дістати з неї папірець (File.ReadAllText), викинути папірець (File.Delete) або навіть витягнути цілу шухляду й відправити її в інший кінець кімнати (Directory.Move). Прості завдання — прості методи.

2. Клас File: що це і навіщо потрібен

Клас File має дуже зручний набір статичних методів для всіх популярних операцій із файлами.

Найчастіше вживані методи

Метод Опис
File.Exists(path)
Перевіряє, чи існує файл за вказаним шляхом.
File.ReadAllText(path)
Зчитує весь файл як текст.
File.ReadAllLines(path)
Зчитує всі рядки файлу в масив.
File.WriteAllText(path, text)
Перезаписує файл указаним текстом.
File.AppendAllText(path, text)
Дописує текст у кінець файлу.
File.Copy(source, destination)
Копіює файл.
File.Delete(path)
Видаляє файл.
File.Move(source, destination)
Переміщує або перейменовує файл.
File.Open/Read/Write/Create
Відкриває потік для складних операцій.

Швидкий приклад: перевіряємо файл і читаємо його

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 — про папки (каталоги).

Основні завдання

Метод Опис
Directory.Exists(path)
Перевіряє, чи існує папка.
Directory.CreateDirectory(path)
Створює папку (або цілий шлях із усіма проміжними папками).
Directory.Delete(path)
Видаляє папку (можна разом із підпапками).
Directory.GetFiles(path)
Отримує список файлів у папці.
Directory.GetDirectories(path)
Отримує список підпапок.
Directory.Move(source, destination)
Переміщує або перейменовує папку.
Directory.GetCurrentDirectory()
Отримує поточну робочу папку застосунку.

Приклад: створюємо папку й зберігаємо туди файл

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, а коли — класи потоків

Ситуація Що використовувати
Потрібно перевірити, чи існує файл/папка
File.Exists, Directory.Exists
Прочитати/записати весь невеликий файл
File.ReadAllText, WriteAllText
Додати текст у кінець файлу
File.AppendAllText
Отримати список файлів у папці
Directory.GetFiles
Копіювати, видалити, перемістити файл
File.Copy/Delete/Move
Копіювати/видалити цілу папку 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 або попередньо перевірте наявність.

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ