Чтение онлайн

на главную

Жанры

Программирование. Принципы и практика использования C++ Исправленное издание
Шрифт:

Одно из основных применений вывода — организация данных для чтения, доступного людям. Вспомните о сообщениях электронной почты, академических статьях, веб-страницах, счетах, деловых отчетах, списках контактов, оглавлениях, показаниях датчиков состояния устройств и т.д. Потоки

ostream
предоставляют много возможностей для форматирования текста по вкусу пользователей. Аналогично, большая часть входной информации записывается людьми или форматируется так, чтоб люди могли ее прочитать. Потоки
istream
обеспечивают возможности для чтения данных, созданных потоками
ostream
. Вопросы, связанные с форматированием, будут рассмотрены в разделе 11.2, а ввод информации, отличающейся от символов, — в разделе 11.3.2. В основном сложность, связанная с вводом данных, обусловлена
обработкой ошибок. Для того чтобы привести более реалистичные примеры, начнем с обсуждения того, как модель потоков ввода-вывода связывает файлы с данными.

10.3. Файлы

Обычно мы имеем намного больше данных, чем способна вместить основная память нашего компьютера, поэтому большая часть информации хранится на дисках или других средствах хранения данных высокой емкости. Такие устройства также предотвращают исчезновение данных при выключении компьютера — такие данные являются персистентными. На самом нижнем уровне файл просто представляет собой последовательность байтов, пронумерованных начиная с нуля.

Файл имеет формат; иначе говоря, набор правил, определяющих смысл байтов. Например, если файл является текстовым, то первые четыре байта представляют собой первые четыре символа. С другой стороны, если файл хранит бинарное представление целых чисел, то первые четыре байта используются для бинарного представления первого целого числа (раздел 11.3.2). Формат по отношению к файлам на диске играет ту же роль, что и типы по отношению к объектам в основной памяти. Мы можем приписать битам, записанным в файле, определенный смысл тогда и только тогда, когда известен его формат (разделы 11.2 и 11.3).

При работе с файлами поток
ostream
преобразует объекты, хранящиеся в основной памяти, в потоки байтов и записывает их на диск. Поток
istream
действует наоборот; иначе говоря, он считывает поток байтов с диска и составляет из них объект.

Чаще всего мы предполагаем, что байты на диске являются символами из обычного набора символов. Это не всегда так, но, поскольку другие представления обработать несложно, мы, как правило, будем придерживаться этого предположения. Кроме того, будем считать, что все файлы находятся на дисках (т.е. на вращающихся магнитных устройствах хранения данных). И опять-таки это не всегда так (вспомните о флэш-памяти), но на данном уровне программирования фактическое устройство хранения не имеет значения. Это одно из главных преимущество абстракций файла и потока.

Для того чтобы прочитать файл, мы должны

• знать его имя;

• открыть его (для чтения);

• считать символы;

• закрыть файл (хотя это обычно выполняется неявно).

Для того чтобы записать файл, мы должны

• назвать его;

• открыть файл (для записи) или создать новый файл с таким именем;

• записать наши объекты;

• закрыть файл (хотя это обычно выполняется неявно).

Мы уже знаем основы чтения и записи, поскольку во всех рассмотренных нами ситуациях поток

ostream
, связанный с файлом, ведет себя точно так же, как поток
cout
, а поток
istream
, связанный с файлом, ведет себя точно так же, как объект
cin
. Операции, характерные только для файлов, мы рассмотрим позднее (в разделе 11.3.3), а пока посмотрим, как открыть файлы, и сосредоточим свое внимание на операциях и приемах, которые можно применить ко всем потокам
ostream
и
istream
.

10.4.

Открытие файла

Если хотите считать данные из файла или записать их в файл, то должны открыть поток специально для этого файла. Поток ifstream — это поток istream для чтения из файла, поток ofstream — это поток ostream для записи в файл, а поток fstream — это поток iostream, который можно использовать как для чтения, так и для записи. Перед использованием файлового потока его следует связать с файлом. Рассмотрим пример.

cout << "Пожалуйста, введите имя файла: ";

string name;

cin >> name;

ifstream ist(name.c_str); // ist — это поток ввода для файла,

// имя которого задано строкой name

if (!ist) error(" Невозможно открыть файл для ввода ",name);

Определение потока ifstream с именем, заданным строкой name, открывает файл с этим именем для чтения. Функция
c_str
— это член класса
string
, создающий низкоуровневую строку в стиле языка С из объекта класса
string
. Такие строки в стиле языка С требуются во многих системных интерфейсах. Проверка
!ist
позволяет выяснить, был ли файл открыт корректно. После этого можно считывать данные из файла точно так же, как из любого другого потока istream. Например, предположим, что оператор ввода
>>
определен для типа
Point
. Тогда мы могли бы написать следующий фрагмент программы:

vector<Point> points;

Point p;

while (ist>>p) points.push_back(p);

Вывод в файлы аналогичным образом можно выполнить с помощью потоков

ofstream
. Рассмотрим пример.

cout << "Пожалуйста, введите имя файла для вывода: ";

string oname;

cin >> oname;

ofstream ost(oname.c_str); // ost — это поток вывода для файла,

// имя которого задано строкой name

if (!ost) error("Невозможно открыть файл вывода ",oname);

Определение потока
ofstream
с именем, заданным строкой
name
, открывает файл с этим именем для чтения. Проверка
!ost
позволяет выяснить, был ли файл открыт корректно. После этого можно записывать данные в файл точно так же, как в любой другой поток
ostream
. Рассмотрим пример.

for (int i=0; i<points.size; ++i)

ost << '(' << points[i].x << ',' << points[i].y << ")\n";

Когда файловый поток выходит из пределов видимости, связанный с ним файл закрывается. Когда файл закрывается, связанный с ним буфер “очищается” (“flushed”); иначе говоря, символы из буфера записываются в файл.

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

Поделиться:
Популярные книги

Сердце Дракона. Том 19. Часть 1

Клеванский Кирилл Сергеевич
19. Сердце дракона
Фантастика:
фэнтези
героическая фантастика
боевая фантастика
7.52
рейтинг книги
Сердце Дракона. Том 19. Часть 1

Последняя Арена 10

Греков Сергей
10. Последняя Арена
Фантастика:
боевая фантастика
рпг
5.00
рейтинг книги
Последняя Арена 10

Идеальный мир для Лекаря 21

Сапфир Олег
21. Лекарь
Фантастика:
фэнтези
юмористическое фэнтези
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 21

Звезда сомнительного счастья

Шах Ольга
Фантастика:
фэнтези
6.00
рейтинг книги
Звезда сомнительного счастья

Live-rpg. эволюция-4

Кронос Александр
4. Эволюция. Live-RPG
Фантастика:
боевая фантастика
7.92
рейтинг книги
Live-rpg. эволюция-4

Девятое правило дворянина

Герда Александр
9. Истинный дворянин
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Девятое правило дворянина

Муж на сдачу

Зика Натаэль
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Муж на сдачу

Para bellum

Ланцов Михаил Алексеевич
4. Фрунзе
Фантастика:
попаданцы
альтернативная история
6.60
рейтинг книги
Para bellum

Егерь

Астахов Евгений Евгеньевич
1. Сопряжение
Фантастика:
боевая фантастика
попаданцы
рпг
7.00
рейтинг книги
Егерь

Вечная Война. Книга VII

Винокуров Юрий
7. Вечная Война
Фантастика:
юмористическая фантастика
космическая фантастика
5.75
рейтинг книги
Вечная Война. Книга VII

Я снова не князь! Книга XVII

Дрейк Сириус
17. Дорогой барон!
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я снова не князь! Книга XVII

Ваантан

Кораблев Родион
10. Другая сторона
Фантастика:
боевая фантастика
рпг
5.00
рейтинг книги
Ваантан

Идущий в тени 4

Амврелий Марк
4. Идущий в тени
Фантастика:
боевая фантастика
6.58
рейтинг книги
Идущий в тени 4

Мятежник

Прокофьев Роман Юрьевич
4. Стеллар
Фантастика:
боевая фантастика
7.39
рейтинг книги
Мятежник