Как прочитать и записать файл — File.ReadAllText
string text = File.ReadAllText("input.txt");
string[] lines = File.ReadAllLines("input.txt");File.ReadAllText читает весь файл в одну строку, File.ReadAllLines — в массив строк, по одной на каждую строку файла. Класс File из System.IO подключён в проектах .NET 6 и новее сам.
Пример: сумма чисел из файла
Файл numbers.txt лежит рядом с программой:
10
20
5string[] lines = File.ReadAllLines("numbers.txt");
int sum = 0;
foreach (string line in lines)
{
if (int.TryParse(line, out int n))
{
sum += n;
}
}
Console.WriteLine($"Строк: {lines.Length}, сумма: {sum}");Строк: 3, сумма: 35TryParse пропускает пустые и нечисловые строки, если они попадутся. Для очень больших файлов вместо ReadAllLines берите File.ReadLines: он читает строки по одной, не загружая весь файл в память, — цикл foreach тот же.
Запись
File.WriteAllText("result.txt", "Сумма: 35\n");
File.AppendAllText("log.txt", $"{DateTime.Now}: запуск\n");
string[] names = { "Анна", "Борис" };
File.WriteAllLines("names.txt", names);WriteAllText— записать строку в файл;AppendAllText— дописать в конец (файл создаётся, если его нет);WriteAllLines— записать массив или список, каждый элемент с новой строки.
WriteAllText и WriteAllLines перезаписывают файл целиком: всё, что в нём было, пропадает без вопросов. Чтобы добавить к содержимому, используйте AppendAllText, а перед записью в важный файл проверьте имя и путь.
Файлы читаются и пишутся в кодировке UTF-8.
Где программа ищет файл
Имя без папки ("numbers.txt") ищется в текущей папке программы:
- при запуске
dotnet runиз папки проекта — в папке проекта; - при запуске из Visual Studio — в папке сборки
bin\Debug\net10.0\(у .NET 8 —net8.0).
Поэтому файл, лежащий рядом с Program.cs, из Visual Studio «не находится»: программа останавливается с FileNotFoundException: Could not find file '...\bin\Debug\net10.0\numbers.txt'. В сообщении виден полный путь, где файл искали. Решения:
- в Visual Studio выделить файл в обозревателе решений и в окне свойств задать свойству Copy to Output Directory значение Copy if newer; тогда файл будет копироваться в
binпри каждой сборке; - указать полный путь:
File.ReadAllText(@"C:\Data\numbers.txt")— с@, чтобы\не считалась особым символом; - искать файл рядом с самой программой:
Path.Combine(AppContext.BaseDirectory, "numbers.txt").
Проверить, есть ли файл, можно заранее: if (File.Exists("numbers.txt")) { ... }.
Построчно: StreamReader
Классический способ, который встречается в учебниках, — StreamReader:
using StreamReader reader = new StreamReader("numbers.txt");
string? line;
while ((line = reader.ReadLine()) != null)
{
Console.WriteLine(line);
}using в начале строки закрывает файл, когда переменная больше не нужна. Без этого файл может остаться занятым, и другая программа не сможет его изменить.
Старая кодировка Windows-1251
Если вместо русских букв в прочитанном тексте «кракозябры», файл, скорее всего, сохранён в старой кодировке Windows-1251. В .NET её нужно подключить один раз в начале программы:
using System.Text;
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
string text = File.ReadAllText("old.txt", Encoding.GetEncoding(1251));
Console.WriteLine(text);Надёжнее один раз пересохранить такой файл в UTF-8: в Блокноте — через «Сохранить как» с выбором кодировки, в VS Code — щелчком по названию кодировки в строке состояния внизу окна.