Чтение и запись текстовых файлов. StreamReader и StreamWriter


Для работы непосредственно с текстовыми файлами в пространстве System.IO определены специальные классы: StreamReader и StreamWriter.

Запись в файл и StreamWriter
Для записи в текстовый файл используется класс StreamWriter. Некоторые из его конструкторов, которые могут применяться для создания объекта StreamWriter:

StreamWriter(string path): через параметр path передается путь к файлу, который будет связан с потоком

StreamWriter(string path, bool append): параметр append указывает, надо ли добавлять в конец файла данные или же перезаписывать файл. Если равно true, то новые данные добавляются в конец файла. Если равно false, то файл перезаписываетсяя заново

StreamWriter(string path, bool append, System.Text.Encoding encoding): параметр encoding указывает на кодировку, которая будет применяться при записи

Свою функциональность StreamWriter реализует через следующие методы:

int Close(): закрывает записываемый файл и освобождает все ресурсы

void Flush(): записывает в файл оставшиеся в буфере данные и очищает буфер.

Task FlushAsync(): асинхронная версия метода Flush

void Write(string value): записывает в файл данные простейших типов, как int, double, char, string и т.д. Соответственно имеет ряд перегруженных версий для записи данных элементарных типов, например, Write(char value), Write(int value), Write(double value) и т.д.

Task WriteAsync(string value): асинхронная версия метода Write. Обратите внимание, что асинхронные версии есть не для всех перегрузок метода Write.

void WriteLine(string value): также записывает данные, только после записи добавляет в файл символ окончания строки

Task WriteLineAsync(string value): асинхронная версия метода WriteLine

Рассмотрим запись в файл на примере:

string path = "note1.txt";
string text = "Hello World\nHello METANIT.COM";

// полная перезапись файла
using (StreamWriter writer = new StreamWriter(path, false))
{
await writer.WriteLineAsync(text);
}
// добавление в файл
using (StreamWriter writer = new StreamWriter(path, true))
{
await writer.WriteLineAsync("Addition");
await writer.WriteAsync("4,5");
}
В данном случае два раза создаем объект StreamWriter. В первом случае если файл существует, то он будет перезаписан. Если не существует, он будет создан. И в нее будет записан текст из переменной text. Во втором случае файл открывается для дозаписи, и будут записаны атомарные данные - строка и число.

По завершении в папке программы мы сможем найти файл note.txt, который будет иметь следующие строки:

Hello World
Hello METANIT.COM
Addition
4,5
В пример выше будет использоваться кодировка по умолчанию. но также можно задать ее явным образом:

using (StreamWriter writer = new StreamWriter(path, true, System.Text.Encoding.Default))
{
// операции с writer
}
Чтение из файла и StreamReader
Класс StreamReader позволяет нам легко считывать весь текст или отдельные строки из текстового файла.

Некоторые из конструкторов класса StreamReader:

StreamReader(string path): через параметр path передается путь к считываемому файлу

StreamReader(string path, System.Text.Encoding encoding): параметр encoding задает кодировку для чтения файла

Среди методов StreamReader можно выделить следующие:

void Close(): закрывает считываемый файл и освобождает все ресурсы

int Peek(): возвращает следующий доступный символ, если символов больше нет, то возвращает -1

int Read(): считывает и возвращает следующий символ в численном представлении. Имеет перегруженную версию: Read(char[] array, int index, int count), где array - массив, куда считываются символы, index - индекс в массиве array, начиная с которого записываются считываемые символы, и count - максимальное количество считываемых символов

Task<int> ReadAsync(): асинхронная версия метода Read

string ReadLine(): считывает одну строку в файле

string ReadLineAsync(): асинхронная версия метода ReadLine

string ReadToEnd(): считывает весь текст из файла

string ReadToEndAsync(): асинхронная версия метода ReadToEnd

Сначала считаем текст полностью из ранее записанного файла:

string path = "note1.txt";
// асинхронное чтение
using (StreamReader reader = new StreamReader(path))
{
string text = await reader.ReadToEndAsync();
Console.WriteLine(text);
}
Считаем текст из файла построчно:

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

// асинхронное чтение
using (StreamReader reader = new StreamReader(path))
{
string? line;
while ((line = await reader.ReadLineAsync()) != null)
{
Console.WriteLine(line);
}
}
В данном случае считываем построчно через цикл while: while ((line = await reader.ReadLineAsync()) != null) - сначала присваиваем переменной line результат функции reader.ReadLineAsync(), а затем проверяем, не равна ли она null. Когда объект sr дойдет до конца файла и больше строк не останется, то метод reader.ReadLineAsync() будет возвращать null.