Работа с файловой системой в C#: от теории к практике
Работа с файловой системой — одна из базовых задач, с которой сталкивается каждый разработчик. Будь то логирование, обработка конфигурационных файлов, импорт данных или создание отчетов — умение грамотно читать, записывать и управлять файлами в C# (.NET) необходимо в любом проекте. В этой статье мы разберем практические примеры работы с файловой системой на C#, начиная от простых операций и заканчивая обработкой директорий.
Мы будем использовать пространство имен System.IO, которое предоставляет все необходимые классы для взаимодействия с файловой системой.
1. Основные классы для работы с файлами и папками
Прежде чем писать код, важно познакомиться с ключевыми классами:
- File — статический класс для создания, копирования, удаления и перемещения файлов.
- FileInfo — экземплярный класс, предоставляющий информацию о конкретном файле и методы для работы с ним.
- Directory — статический класс для работы с папками.
- DirectoryInfo — экземплярный класс для получения информации о папке.
- Path — утилитарный класс для работы с путями к файлам.
Рассмотрим простейший пример — проверку существования файла и его создание:
using System;
using System.IO;
class Program
{
static void Main()
{
string filePath = @"C:\Test\example.txt";
if (File.Exists(filePath))
{
Console.WriteLine("Файл существует.");
}
else
{
File.Create(filePath).Close();
Console.WriteLine("Файл создан.");
}
}
}
Обратите внимание: после File.Create() мы вызываем Close(), чтобы освободить поток. В современных проектах лучше использовать конструкцию using.
2. Чтение и запись текстовых файлов
Самый распространенный сценарий — чтение и запись текстовой информации. В C# для этого есть удобные классы StreamReader и StreamWriter.
2.1 Запись данных в файл
Пример записи строк в файл с использованием StreamWriter:
string path = @"C:\Test\log.txt";
string[] lines = { "Первая строка", "Вторая строка", "Третья строка" };
using (StreamWriter writer = new StreamWriter(path, false))
{
foreach (string line in lines)
{
writer.WriteLine(line);
}
}
Console.WriteLine("Данные записаны.");
Второй параметр конструктора StreamWriter — false означает перезапись файла. Если указать true, данные будут добавляться в конец.
2.2 Чтение данных из файла
Чтение всего содержимого или построчно:
string path = @"C:\Test\log.txt";
// Чтение всего текста одной строкой
string allText = File.ReadAllText(path);
Console.WriteLine("Весь текст:\n" + allText);
// Построчное чтение
string[] allLines = File.ReadAllLines(path);
Console.WriteLine("Построчно:");
foreach (string line in allLines)
{
Console.WriteLine(line);
}
Для больших файлов лучше использовать StreamReader с построчным чтением в цикле, чтобы не загружать весь файл в память.
using (StreamReader reader = new StreamReader(path))
{
string currentLine;
while ((currentLine = reader.ReadLine()) != null)
{
Console.WriteLine(currentLine);
}
}
3. Работа с бинарными файлами (FileStream)
Когда нужно работать с бинарными данными (изображения, архивы, сериализованные объекты), используется класс FileStream. Он позволяет читать и записывать данные в виде байтов.
Пример записи и чтения массива байт:
string binaryPath = @"C:\Test\data.bin";
byte[] dataToWrite = { 0x48, 0x65, 0x6C, 0x6C, 0x6F }; // "Hello" в ASCII
// Запись
using (FileStream fs = new FileStream(binaryPath, FileMode.Create))
{
fs.Write(dataToWrite, 0, dataToWrite.Length);
}
Console.WriteLine("Бинарные данные записаны.");
// Чтение
byte[] dataRead = new byte[dataToWrite.Length];
using (FileStream fs = new FileStream(binaryPath, FileMode.Open))
{
fs.Read(dataRead, 0, dataRead.Length);
}
Console.WriteLine("Прочитано: " + System.Text.Encoding.ASCII.GetString(dataRead));
Режимы FileMode определяют, как открывается файл: Create, Open, Append и другие.
4. Управление папками и поиск файлов
Часто требуется не просто работать с одним файлом, а управлять целыми директориями: создавать, перемещать, получать список файлов.
4.1 Создание и удаление папок
string dirPath = @"C:\Test\NewFolder";
if (!Directory.Exists(dirPath))
{
Directory.CreateDirectory(dirPath);
Console.WriteLine("Папка создана.");
}
// Удаление папки (если она пуста)
Directory.Delete(dirPath);
Console.WriteLine("Папка удалена.");
Чтобы удалить непустую папку, используйте перегрузку с параметром true: Directory.Delete(dirPath, true).
4.2 Получение списка файлов и подпапок
string targetDir = @"C:\Test";
// Все файлы в папке
string[] files = Directory.GetFiles(targetDir);
Console.WriteLine("Файлы в папке:");
foreach (string file in files)
{
Console.WriteLine(Path.GetFileName(file));
}
// Все подпапки
string[] subDirs = Directory.GetDirectories(targetDir);
Console.WriteLine("Подпапки:");
foreach (string dir in subDirs)
{
Console.WriteLine(Path.GetFileName(dir));
}
// Поиск всех файлов .txt, включая подпапки
string[] txtFiles = Directory.GetFiles(targetDir, "*.txt", SearchOption.AllDirectories);
Console.WriteLine("Все txt-файлы:");
foreach (string file in txtFiles)
{
Console.WriteLine(file);
}
Использование SearchOption.AllDirectories позволяет рекурсивно обходить все вложенные папки.
5. Дополнительные полезные приемы
- Копирование и перемещение:
File.Copy(source, dest, overwrite)иFile.Move(source, dest). - Получение информации о