Ввод-вывод данных на нижнем уровне осуществляется функциями геаd( ) и write( ). Прототипы этих функций имеют следующий вид:
int read(intfd, char*buffer, unsigned intcount);
int write(intfd, char*buffer, unsigned intcount);
Обе функции возвращают целое число - количество действительно прочитанных или записанных байтов.
Функция 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> и <С>).