ОСНОВЫФАЙЛОВОГО ВВОДА-ВЫВОДА
КЛАССИФИКАЦИЯ СПОСОБОВ ВВОДА-ВЫВОДА
В этой лекции мы рассмотрим способы ввода-вывода с использованием потоков и файлов и соответствующие средства языка C++. Система программирования MVC++ (MicrosoftVisualC++) обеспечивает следующие варианты организации ввода-вывода:
è прямой небуферизованный ввод-вывод с помощью библиотеки С времени выполнения;
è ввод-вывод с помощью потоковых средств стандарта ANSI С;
è ввод-вывод для консоли и порта;
è ввод-вывод с помощью библиотеки MFC;
è ввод-вывод с помощью стандартной библиотеки C++.
Перечисленные варианты организации ввода-вывода можно классифицировать по двум основным признакам:
è стилю программирования;
è уровню взаимодействия с внешними устройствами.
По стилю программирования в C++ можно выделить объектно-ориентированную систему ввода-вывода и три унаследованные процедурно-ориентированные системы ввода-вывода языка С: потоковые средства библиотеки стандарта ANSI C, систему ввода-вывода для консоли и порта, средства низкоуровневого ввода/вывода.
Базовые объектно-ориентированные средства ввода-вывода, обеспечивающие работу с потоками, объявлены в файле iostream.h. При подключении файла iostream.h, становятся доступны объектно-ориентированные средства обмена данными между программой и файлами через потоки. В файле sstream.h объявлены средства обмена данными с областью памяти, которая рассматривается как массив символов или как строка типа string.
Процедурно-ориентированные средства реализованы с помощью бибилиотеки стандартного ввода-вывода ANSI C и становятся доступными при подключении в программе заголовочного файла stdio.h.
По уровню взаимодействия с внешними устройствами различают ввод-вывод:
è на верхнем уровне;
è на нижнем уровне;
è на уровне консоли и порта.
При взаимодействии с внешними устройствами на верхнем уровне используется форматированный ввод-вывод, при этом передаваемые байты группируются в элементы данных определенного типа: целые числа, числа с плавающей точкой, отдельные символы, строки и данные определенных пользователем типов. Достоинством такого подхода является удобство передачи различных типов данных, а недостатком – высокий уровень накладных расходов при передаче файлов большого объема.
При работе на нижнем уровне выполняется неформатированный ввод-вывод, суть которого заключается в простой пересылке байтов данных между оперативной памятью и внешними устройствами. При этом каждый байт является самостоятельным элементом данных. Достоинством такого подхода является высокая скорость передачи данных, а недостатком – неудобство использования при передаче данных разных типов.
При работе на уровне консоли и порта выполняется прямая запись и чтение данных для соответствующего устройства. Консольные средства обмена данными несовместимы со средствами потокового ввода-вывода и средствами ввода-вывода на нижнем уровне. Кроме того, для консоли и порта не требуется выполнять операции открытия и закрытия потока.
В дополнении к данной классификации по типам передаваемых данных различают два варианта организации ввода-вывода:
è для базовых типов;
è для пользовательских типов.
Средства ввода-вывода в языке С++ реализованы в виде библиотечных перегруженных операций << и >> (извлечения и вставки), манипуляторов, классов потоков, констант, глобальных переменных, функций и типов данных. Мы рассмотрим два важнейших понятия: поток и файл – и принципы организации обмена данными с файлами через потоки.
ПРИНЦИПЫРАБОТЫС ПОТОКАМИ И ФАЙЛАМИ
Поток (stream) можно определить как абстрактный канал связи, который создается в программе для обмена данными с файлами. Это понятие введено для того, чтобы можно было не учитывать особенности организации канала связи между источником и приемником информации.
У всех потоков имеются общие свойства. Поэтому одинаковые средства (операции и функции) могут применяться для работы с различными потоками.
Файл (file) представляет собой поименованную совокупность данных, находящуюся на внешнем устройстве и имеющую определенные атрибуты (характеристики).
Обычно файл рассматривается как последовательность байтов или символов, имеет начало (перед первым байтом), конец (после последнего байта), и при продвижении от начала к концу каждый байт находится в определенной позиции. Начало файла и первый байт имеют нулевую позицию, каждый следующий байт имеет позицию на единицу больше предыдущего. Начало файла имеет позицию, равную нулю, а позиция конца файла равна размеру файла в байтах.
С точки зрения высокоуровневых средств ввода-вывода C++ все файлы разделяются на текстовые и бинарные. С ними можно работать только после того, как в программе установлена их взаимосвязь с текстовыми и бинарными потоками, соответственно.
Файл называется текстовым, если он рассматривается как последовательность строк символов, разделенных не пробельными символами. Кроме пробела, пробельными символами являются следующие специальные символы:
Ø \t — табуляция горизонтальная;
Ø \v — табуляция вертикальная;
Ø \n — новая строка;
Ø \r — возврат каретки;
Ø \f— перевод формата (страницы).
Среди пробельных символов выделяется символ \n (новая строка), который используется для стандартного разделения совокупностей строк на файловые строки (линии, line). Строки символов в текстовых файлах представляют собой последовательности не пробельных символов, которые могут интерпретироваться при вводе как данные определенного типа, представленные в некотором формате. Например, последовательность символов 125, ограниченная с двух сторон пробельными символами, может быть преобразована при вводе в вещественное число типа double или целое число типа int.
Файл называется бинарным, если с ним работают как с последовательностью байтов или символов. Бинарные потоки и файлы обычно используются при перегрузке операций извлечения » и вставки «для пользовательских типов данных или реализации специфических методов ввода-вывода для пользовательских классов.
В качестве файлов рассматриваются не только файлы на дисках, но и устройства, с которыми можно осуществлять операции ввода-вывода, файлами являются клавиатура и дисплей, а также модем, принтер и подключенные внешние устройства.
Не все файлы имеют одинаковые свойства в связи с различным их назначением и физической реализацией. Например, для файлов на CD ROM возможны только операции ввода. Поэтому при связывании потока с определенным файлом поток приобретает его свойства. Можно говорить о записи в поток и чтении из потока, что эквивалентно записи в файл и чтению из файла.
При работе с потоками и файлами различают буферизованный и небуферизованный ввод-вывод. Буфер (buffer) представляет собой область оперативной памяти, которую используют средства ввода-вывода для промежуточного хранения данных, передаваемых между программой и внешним устройством. Буфер может быть системным, в этом случае область памяти, где размещаются системные буферы, принадлежит операционной системе, а не программе.
Вывод данных в поток с буфером приводит к выводу этих данных в соответствующий файл только после заполнения буфера. Вывод данных в небуферизованный поток приводит к немедленному выводу их в файл.
Использование буферов позволяет ускорить работу с потоком путем поблочного (а не побайтного) обмена данными. Вместе с тем, наличие буфера приводит к накладным расходам. При вводе данных возможны ошибки, следовательно, требуется контролировать и обеспечивать корректность содержимого буфера перед выполнением очередной операции ввода. Далее, из-за возможности аварийного завершения программы в связи со сбоем при выводе данных необходимо обеспечивать периодическое сохранение содержимого буфера в файле. И, наконец, при синхронизации работы потоков наличие буферов также должно учитываться.
Рассмотрим подробнее виды и общие свойства потоков, которые позволяют создавать стандартные средства C++.