Файлы и потоки: углублённо
fstream, форматирование, двоичный и текстовый режим, состояние ошибок
Главная идея: В C++ любой источник ввода и вывода — клавиатура, экран, файл на диске и даже строка в памяти — описывается одной и той же абстракцией: потоком. Как только вы поймёте потоки, чтение файла почти не будет отличаться от чтения
std::cin. Эта тема выводит вас за рамки начального рецепта "открыть, прочитать, закрыть" и раскрывает детали, важные в реальных программах: режимы открытия, форматирование вывода, разницу между текстовым и двоичным вводом-выводом и способы проверки того, что операция действительно удалась.
К концу вы сможете:
- выбирать правильный тип потока и режим открытия под задачу,
- надёжно читать файлы с правильной идиомой цикла,
- управлять оформлением вывода с помощью манипуляторов (
setw,setprecision,fixed,hex, ...), - читать и записывать двоичные данные и понимать, когда текстовый режим вас подводит,
- проверять состояние ошибок (
good,eof,fail,bad) и восстанавливаться после сбоя.
1. Семейство потоков
Поток — это объект, представляющий текущую последовательность байтов между вашей программой и неким устройством. Стандартная библиотека предоставляет небольшую иерархию, объявленную в заголовках <iostream>, <fstream> и <sstream>:
std::istream— базовый тип, из которого можно читать (std::cin— один из них).std::ostream— базовый тип, в который можно писать (std::cout,std::cerr).std::ifstream— входной файловый поток.std::ofstream— выходной файловый поток.std::fstream— файловый поток, умеющий и то, и другое.std::istringstream/std::ostringstream— потоки поверх строки в памяти, идеальны для разбора и сборки текста.
Выгода в единообразии: любая функция, принимающая std::istream&, охотно примет и std::cin, и std::ifstream, и std::istringstream. Напишите код разбора один раз — и он работает с файлами, консолью и тестовыми строками.
fstream наследует от обеих сторон, поэтому умеет и читать, и писать. Любой код, написанный под базовые типы, работает с каждым конкретным потоком.