Работа с файлами. Классы File и FileInfo


Подобно паре Directory/DirectoryInfo для работы с файлами предназначена пара классов File и FileInfo. С их помощью мы можем создавать, удалять, перемещать файлы, получать их свойства и многое другое.

FileInfo
Некоторые полезные методы и свойства класса FileInfo:

CopyTo(path): копирует файл в новое место по указанному пути path

Create(): создает файл

Delete(): удаляет файл

MoveTo(destFileName): перемещает файл в новое место

Свойство Directory: получает родительский каталог в виде объекта DirectoryInfo

Свойство DirectoryName: получает полный путь к родительскому каталогу

Свойство Exists: указывает, существует ли файл

Свойство Length: получает размер файла

Свойство Extension: получает расширение файла

Свойство Name: получает имя файла

Свойство FullName: получает полное имя файла

Для создания объекта FileInfo применяется конструктор, который получает в качестве параметра путь к файлу:

FileInfo fileInf = new FileInfo(@"C:\app\content.txt");
File
Класс File реализует похожую функциональность с помощью статических методов:

Copy(): копирует файл в новое место

Create(): создает файл

Delete(): удаляет файл

Move: перемещает файл в новое место

Exists(file): определяет, существует ли файл

Пути к файлам
Для работы с файлами можно применять как абсолютные, так и относительные пути:

// абсолютные пути
string path1 = @"C:\Users\eugene\Documents\content.txt"; // для Windows
string path2 = "C:\\Users\\eugene\\Documents\\content.txt"; // для Windows
string path3 = "/Users/eugene/Documents/content.txt"; // для MacOS/Linux

// относительные пути
string path4 = "MyDir\\content.txt"; // для Windows
string path5 = "MyDir/content.txt"; // для MacOS/Linux
Получение информации о файле

string path = @"C:\Users\eugene\Documents\content.txt";
// string path = "/Users/eugene/Documents/content.txt"; // для MacOS/Linux
FileInfo fileInfo = new FileInfo(path);
if (fileInfo.Exists)
{
Console.WriteLine($"Имя файла: {fileInfo.Name}");
Console.WriteLine($"Время создания: {fileInfo.CreationTime}");
Console.WriteLine($"Размер: {fileInfo.Length}");
}
Удаление файла

string path = @"C:\app\content.txt";
FileInfo fileInf = new FileInfo(path);
if (fileInf.Exists)
{
fileInf.Delete();
// альтернатива с помощью класса File
// File.Delete(path);
}
Перемещение файла

string path = @"C:\OldDir\content.txt";
string newPath = @"C:\NewDir\index.txt";
FileInfo fileInf = new FileInfo(path);
if (fileInf.Exists)
{
fileInf.MoveTo(newPath);
// альтернатива с помощью класса File
// File.Move(path, newPath);
}
Если файл по новому пути уже существует, то с помощью дополнительного параметра можно указать, надо ли перезаписать файл (при значении true файл перезаписывается)

string path = @"C:\OldDir\content.txt";
string newPath = @"C:\NewDir\index.txt";
FileInfo fileInf = new FileInfo(path);
if (fileInf.Exists)
{
fileInf.MoveTo(newPath, true);
// альтернатива с помощью класса File
// File.Move(path, newPath, true);
}
Копирование файла

string path = @"C:\OldDir\content.txt";
string newPath = @"C:\NewDir\index2.txt";
FileInfo fileInf = new FileInfo(path);
if (fileInf.Exists)
{
fileInf.CopyTo(newPath, true);
// альтернатива с помощью класса File
// File.Copy(path, newPath, true);
}
Метод CopyTo класса FileInfo принимает два параметра: путь, по которому файл будет копироваться, и булевое значение, которое указывает, надо ли при копировании перезаписывать файл (если true, как в случае выше, файл при копировании перезаписывается). Если же в качестве последнего параметра передать значение false, то если такой файл уже существует, приложение выдаст ошибку.

Метод Copy класса File принимает три параметра: путь к исходному файлу, путь, по которому файл будет копироваться, и булевое значение, указывающее, будет ли файл перезаписываться.

Чтение и запись файлов
В дополнение к вышерассмотренным методам класс File также предоставляет ряд методов для чтения-записи текстовых и бинарных файлов:

AppendAllLines(String, IEnumerable<String>) / AppendAllLinesAsync(String, IEnumerable<String>, CancellationToken)

добавляют в файл набор строк. Если файл не существует, то он создается

AppendAllText(String, String) / AppendAllTextAsync(String, String, CancellationToken)

добавляют в файл строку. Если файл не существует, то он создается

byte[] ReadAllBytes (string path) / Task<byte[]> ReadAllBytesAsync (string path, CancellationToken cancellationToken)

считывают содержимое бинарного файла в массив байтов

string[] ReadAllLines (string path) / Task<string[]> ReadAllLinesAsync (string path, CancellationToken cancellationToken)

считывают содержимое текстового файла в массив строк

string ReadAllText (string path) / Task<string> ReadAllTextAsync (string path, CancellationToken cancellationToken)

считывают содержимое текстового файла в строку

IEnumerable<string> ReadLines (string path)

считывают содержимое текстового файла в коллекцию строк

void WriteAllBytes (string path, byte[] bytes) / Task WriteAllBytesAsync (string path, byte[] bytes, CancellationToken cancellationToken)

записывают массив байт в бинарный файл. Если файл не существует, он создается. Если существует, то перезаписывается

void WriteAllLines (string path, string[] contents) / Task WriteAllLinesAsync (string path, IEnumerable<string> contents, CancellationToken cancellationToken)

записывают массив строк в текстовый файл. Если файл не существует, он создается. Если существует, то перезаписывается

WriteAllText (string path, string? contents) / Task WriteAllTextAsync (string path, string? contents, CancellationToken cancellationToken)

записывают строку в текстовый файл. Если файл не существует, он создается. Если существует, то перезаписывается

Как видно, эти методы покрывают практически все основные сценарии - чтение и запись текстовых и бинарных файлов. Причем в зависимости от задачи можно применять как синхронные методы, так и их асинхронные аналоги.

Например, запишем и считаем обратно в строку текстовый файл:

string path = @"c:\app\content.txt";

string originalText = "Hello Metanit.com";
// запись строки
await File.WriteAllTextAsync(path, originalText);
// дозапись в конец файла
await File.AppendAllTextAsync(path, "\nHello work");

// чтение файла
string fileText = await File.ReadAllTextAsync(path);
Console.WriteLine(fileText);
Консольный вывод:

Hello Metanit.com
Hello work
Стоит отметить, что при добавлении текста я добавил в строку последовательность "\n", которая выполняет перевод на следующую строку. Благодаря этому добавляемый текст располагается в файле на новой строке.

Если мы хотим, что в файле изначально шло добавление на новую строку, то для записи стоит использовать метод WriteAllLines/ WriteAllLinesAsync, а для добавления - AppendAllLines / AppendAllLinesAsync

await File.WriteAllLinesAsync(path, new[] { "Hello Metanit.com", "Hello work" });
Аналогично при чтении файла если мы хотим каждую строку файла считать отдельно, то вместо ReadAllText / ReadAllTextAsync применяется ReadAllLines / ReadAllTextAsync.

Кодировка
В качестве дополнительного параметра методы чтения-записи текстовых файлов позволяют установить кодировку в виде объекта System.Text.Encoding:

using System.Text;

string path = "/Users/eugene/Documents/app/content.txt";

string originalText = "Привет Metanit.com";
// запись строки
await File.WriteAllTextAsync(path, originalText, Encoding.Unicode);
// дозапись в конец файла
await File.AppendAllTextAsync(path, "\nПривет мир", Encoding.Unicode);

// чтение файла
string fileText = await File.ReadAllTextAsync(path, Encoding.Unicode);
Console.WriteLine(fileText);
Для установки кодировки при записи и чтении здесь применяется встроенное значение Encoding.Unicode. Также можно указать название кодировки, единственное следует удостовериться, что текущая операционная система поддерживает выбранную кодировку:

using System.Text;

string path = @"c:\app\content.txt";

string originalText = "Hello Metanit.com";
// запись строки
await File.WriteAllTextAsync(path, originalText, Encoding.GetEncoding("iso-8859-1"));
// дозапись в конец файла
await File.AppendAllTextAsync(path, "\nHello code", Encoding.GetEncoding("iso-8859-1"));

// чтение файла
string fileText = await File.ReadAllTextAsync(path, Encoding.GetEncoding("iso-8859-1"));
Console.WriteLine(fileText);