logo
Подбельский Фомин_Программирование на языке СИ_

7.2.2. Чтение и запись данных

Ввод-вывод данных на нижнем уровне осуществляется функциями геаd( ) и write( ). Прототипы этих функций имеют следующий вид:

int read(int fd, char *buffer, unsigned int count);

int write(int fd, char *buffer, unsigned int count);

Обе функции возвращают целое число - количество действительно прочитанных или записанных байтов.

Функция read( ) читает количество байтов, заданное третьим параметром count, из файла, открытого с дескриптором файла fd, в буфер, определенный указателем buffer. При достижении конца файла функция read( ) возвращает значение 0. В случае возникновения ошибки при чтении из файла функция read( ) возвращает значение -1.

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

Если файл открыт в текстовом режиме, то происходят точно такие же преобразования при вводе последовательности символов CR и LF в символ '\n' (LF), как и при работе с потоком. Указанное преобразование приводит к тому, что в возвращаемом значении вместо двух символов CR и LF учитывается только один символ '\n' (LF).

Функция write( ) записывает последовательность байтов, количество которых задано третьим параметром count, в файл, открытый с дескриптором файла fd, из буфера, определенного указателем buffer. Запись производится с текущей позиции. Если файл открыт в текстовом режиме, то количество реально записанных байтов может превышать count за счет преобразований всех символов V в последовательности символов CR, LF. Таким образом, count будет содержать только количество символов, взятых из буфера.

Если при выполнении операции записи возникла ошибка, то функция write( ) возвращает значение -1, а глобальная переменная errno получает одно из следующих значений, заданных предопределенными константами в заголовочном файле errno.h:

EACCES - файл защищен для записи (доступен только для чтения);

ENOSPC - исчерпано свободное пространство на внешнем устройстве;

EBADF - недействительный дескриптор файла.

Приведем два примера применения функций низкоуровневого ввода-вывода.

Пример 1 .

Копирование последовательности отдельных символов из стандартного ввода в стандартный вывод:

В текст программы включается заголовочный файл io.h, содержащий прототипы функций read( ) и write( ). При вызове этих функций для файлов стандартного ввода и стандартного вывода используются соответственно значения дескрипторов стандартных файлов 0 и 1. Прочитанный символ и код клавиши <Enter>, который служит признаком завершения набора вводимой последовательности символов, записываются в одномерный массив с[ ] из 2 байтов, откуда они затем функцией write( ) выводятся на экран дисплея.

Запустив программу на выполнение, можно вводить одиночные символы с клавиатуры, завершая ввод каждого из них нажатием на клавишу <Enter>. Результат работы программы может выглядеть так:

Первый символ из пары одинаковых символов (v-v; w-w и т.д.) - это символ, введенный с клавиатуры и выведенный системой ввода-вывода на экран (стандартный режим ввода данных с клавиатуры). Второй символ пары выведен на устройство стандартного вывода функцией write( ). Программа копирования завершает работу при вводе сигнала прерывания (одновременном нажатии клавиш <Ctrl> и <С>).

Пример 2.

Копирование произвольного файла

Программа получает имена файлов из командной строки при запуске и позволяет копировать произвольные файлы, (см. аналог этой программы в §7.1.3).

Константа BUFSIZ (размер буфера для потокового ввода-вывода) определена в заголовочном файле stdio.h. Ее значение для MS-DOS равно 512 байт.

Для применения этой программы в ОС MS-DOS необходимо вначале построить исполняемую программу (см. гл. 9), например, copyf.exe. Вызов программы из командной строки будет иметь вид:

где -файл-источник;

- файл-приемник.

Если ошибок при исполнении программы нет, файл будет скопирован, но никаких сообщений на экране дисплея не появится.