9_Работа с файловой системой
Урок 9 : Работа с файловой системой
Файлы позволяют сохранять данные после завершения программы. В этом уроке мы научимся работать с путями и каталогами, выполнять основные операции с файлами, а также читать и записывать обычный текст.
1. Файлы, каталоги и пути
Файл - именованная область на диске, в которой хранятся данные. Например: player.txt, settings.ini, log.txt.
Каталог или папка - контейнер для файлов и других каталогов.
Путь указывает расположение файла или каталога в файловой системе.
Data/player.txt
C:\Games\MyGame\Data\player.txt
Пути бывают двух видов:
- Абсолютный путь содержит полный адрес от корня диска:
C:\Games\MyGame\Data\player.txt. - Относительный путь строится относительно текущей рабочей директории программы:
Data\player.txt.
Текущую рабочую директорию можно получить через Directory.GetCurrentDirectory():
using System.IO;
string currentDirectory = Directory.GetCurrentDirectory();
Console.WriteLine(currentDirectory);
Относительный путь считается не от файла с кодом, а от текущей рабочей директории запущенного приложения. Она может отличаться при запуске программы из IDE и из собранного приложения.
2. Построение путей с помощью Path
Пути не следует собирать обычной конкатенацией строк:
// Ненадёжный вариант
string path = Directory.GetCurrentDirectory() + "\\Data\\player.txt";
Класс Path строит путь с корректными для операционной системы разделителями:
string dataDirectory = Path.Combine(
Directory.GetCurrentDirectory(),
"Data"
);
string filePath = Path.Combine(dataDirectory, "player.txt");
Console.WriteLine(dataDirectory);
Console.WriteLine(filePath);
Полезные методы Path
string path = Path.Combine("Data", "Saves", "player.txt");
Console.WriteLine(Path.GetFileName(path)); // player.txt
Console.WriteLine(Path.GetFileNameWithoutExtension(path)); // player
Console.WriteLine(Path.GetExtension(path)); // .txt
Console.WriteLine(Path.GetDirectoryName(path)); // Data\Saves
Console.WriteLine(Path.IsPathRooted(path)); // false
| Метод | Назначение |
|---|---|
Path.Combine() |
Объединяет части пути |
Path.GetFileName() |
Возвращает имя файла |
Path.GetFileNameWithoutExtension() |
Возвращает имя без расширения |
Path.GetExtension() |
Возвращает расширение файла |
Path.GetDirectoryName() |
Возвращает путь к каталогу |
Path.IsPathRooted() |
Проверяет, является ли путь абсолютным |
3. Работа с каталогами
Класс Directory содержит статические методы для работы с каталогами.
Проверка и создание каталога
string dataDirectory = Path.Combine(
Directory.GetCurrentDirectory(),
"Data"
);
if (!Directory.Exists(dataDirectory))
{
Directory.CreateDirectory(dataDirectory);
Console.WriteLine("Каталог Data создан");
}
Directory.CreateDirectory() безопасно вызывать, даже если каталог уже существует:
Directory.CreateDirectory(dataDirectory);
Если каталога нет, он будет создан. Если каталог существует, ошибка не возникнет.
Получение списка файлов
string[] files = Directory.GetFiles(dataDirectory);
foreach (string file in files)
{
Console.WriteLine(Path.GetFileName(file));
}
Можно искать только файлы с определённым расширением:
string[] textFiles = Directory.GetFiles(dataDirectory, "*.txt");
Другие операции
string[] directories = Directory.GetDirectories(dataDirectory);
Directory.Move("OldData", "NewData");
// Второй аргумент true разрешает удалить непустой каталог
Directory.Delete("TemporaryData", true);
Directory.Delete(path, true) удаляет каталог вместе со всем содержимым. Перед вызовом необходимо внимательно проверить путь.
4. Работа с файлами
Класс File предоставляет статические методы для создания, чтения, копирования, перемещения и удаления файлов.
string sourcePath = Path.Combine("Data", "player.txt");
string copyPath = Path.Combine("Data", "player_copy.txt");
if (File.Exists(sourcePath))
{
File.Copy(sourcePath, copyPath, overwrite: true);
Console.WriteLine("Файл скопирован");
}
Основные операции:
bool exists = File.Exists(sourcePath);
File.Copy(sourcePath, copyPath, overwrite: true);
File.Move(copyPath, Path.Combine("Data", "player_old.txt"));
File.Delete(sourcePath);
| Метод | Назначение |
|---|---|
File.Exists() |
Проверяет существование файла |
File.Copy() |
Копирует файл |
File.Move() |
Перемещает или переименовывает файл |
File.Delete() |
Удаляет файл |
File.Delete() не выбрасывает исключение, если файла нет, но может завершиться ошибкой, если нет прав доступа или файл используется другой программой.
5. Чтение и запись TXT
TXT - обычный текстовый файл. В нём нет обязательной структуры: программа сама определяет, что означает каждая строка.
Запись текста
string dataDirectory = Path.Combine(
Directory.GetCurrentDirectory(),
"Data"
);
Directory.CreateDirectory(dataDirectory);
string filePath = Path.Combine(dataDirectory, "player.txt");
string text = "Имя: Alex\nУровень: 5\nОчки: 1250";
File.WriteAllText(filePath, text);
File.WriteAllText() создаёт файл, если его нет. Если файл уже существует, старое содержимое будет заменено.
Чтение всего файла
if (File.Exists(filePath))
{
string textFromFile = File.ReadAllText(filePath);
Console.WriteLine(textFromFile);
}
else
{
Console.WriteLine("Файл не найден");
}
Запись и чтение набора строк
string[] lines =
{
"Имя: Alex",
"Уровень: 5",
"Очки: 1250"
};
File.WriteAllLines(filePath, lines);
string[] loadedLines = File.ReadAllLines(filePath);
foreach (string line in loadedLines)
{
Console.WriteLine(line);
}
Добавление текста
string notesPath = Path.Combine(dataDirectory, "notes.txt");
File.AppendAllText(notesPath, "Новая строка\n");
В отличие от WriteAllText, метод AppendAllText не стирает существующие данные, а добавляет текст в конец.
| Метод | Результат |
|---|---|
File.WriteAllText() |
Записывает строку, заменяя старое содержимое |
File.ReadAllText() |
Читает весь файл в одну строку |
File.WriteAllLines() |
Записывает коллекцию строк |
File.ReadAllLines() |
Читает файл в массив строк |
File.AppendAllText() |
Добавляет текст в конец файла |
6. StreamWriter и StreamReader
Методы File.ReadAllText() и File.WriteAllText() удобны для небольших файлов. Они загружают или записывают содержимое целиком.
Для последовательной работы с данными используются потоки:
StreamWriterпоследовательно записывает текст;StreamReaderпоследовательно читает текст.
Запись через StreamWriter
string filePath = Path.Combine("Data", "player.txt");
using (StreamWriter writer = new StreamWriter(filePath))
{
writer.WriteLine("Имя: Alex");
writer.WriteLine("Уровень: 5");
writer.WriteLine("Очки: 1250");
}
Чтение через StreamReader
using (StreamReader reader = new StreamReader(filePath))
{
while (!reader.EndOfStream)
{
string line = reader.ReadLine();
Console.WriteLine(line);
}
}
Конструкция using гарантирует закрытие файла после завершения блока, даже если во время работы возникла ошибка.
Современная сокращённая запись:
using StreamWriter writer = new StreamWriter(filePath);
writer.WriteLine("Первая строка");
writer.WriteLine("Вторая строка");
Потоки полезны для больших файлов и последовательной обработки данных. Для небольших текстовых файлов методы класса File обычно проще.
7. Информация о файле
Класс FileInfo представляет информацию о конкретном файле:
FileInfo info = new FileInfo(filePath);
Console.WriteLine($"Имя: {info.Name}");
Console.WriteLine($"Расширение: {info.Extension}");
Console.WriteLine($"Размер: {info.Length} байт");
Console.WriteLine($"Создан: {info.CreationTime}");
Console.WriteLine($"Изменён: {info.LastWriteTime}");
Получение информации обо всех файлах каталога:
foreach (string file in Directory.GetFiles(dataDirectory))
{
FileInfo info = new FileInfo(file);
Console.WriteLine($"{info.Name} | {info.Length} байт");
}
8. Возможные ошибки
Частые причины ошибок при работе с файловой системой:
- файл или каталог не существует;
- путь содержит недопустимые символы;
- у программы нет прав доступа;
- файл открыт другой программой;
- на диске закончилось свободное место.
Перед чтением необходимо проверять существование файла:
if (!File.Exists(filePath))
{
Console.WriteLine("Файл не найден");
return;
}
string text = File.ReadAllText(filePath);
Проверка File.Exists() не защищает от всех возможных проблем. Обработка исключений будет подробно рассмотрена в отдельном уроке.
На этом этапе важно:
- Создавать каталог перед записью.
- Проверять наличие файла перед чтением.
- Закрывать потоки с помощью
using. - Не удалять и не перезаписывать файлы без необходимости.
Итог урока
- Пространство имён
System.IOсодержит инструменты для работы с файловой системой Path.Combine()безопасно объединяет части путиDirectoryпозволяет создавать каталоги и получать список файловFileсодержит методы чтения, записи, копирования, перемещения и удаления файловFileInfoпредоставляет имя, расширение, размер и даты файлаStreamWriterиStreamReaderиспользуются для последовательной работы с текстом- Перед чтением файла следует проверить его существование
- Потоки необходимо закрывать с помощью
using
📋 Перейти к практическим заданиям урока 9
Материалы для дополнительного ознакомления :
Файлы и каталоги
Работа с классом File
FileStream
StreamReader и StreamWriter