Шаг 72.
Работа с файлами. Функции низкоуровневого ввода/вывода

    На этом шаге мы рассмотрим правила и функции работы с файлами "на низком уровне".

    Компьютер "рассматривает" содержимое любого файла как последовательность байтов, интерпретацию которых осуществляют функции высокоуровневого ввода/вывода. Однако в некоторых случаях эту интерпретацию должен осуществлять сам программист. Для реализации этой задачи в C++ имеются функции низкоуровневого ввода/вывода. Перечислим функции, позволяющие работать с файлами на низком уровне. Если не оговорено особо, то заголовочный файл io.h.

Таблица 1. Функции работы с файлами на низком уровне
Функция
Описание
int open (<имя файла>,<доступ>,<дополнительный доступ>);
Открывает файл в заданном режиме. Функция возвращает дескриптор файла, который затем используется в других функциях работы с файлами. Второй параметр может принимать следующие значения (они записаны в заголовочном файле fcntl.h): O_RDONLY (только чтение); O_WRONLY (только запись); O_RDWR (чтение и запись), объединенная с помощью логической операции ИЛИ с требуемой комбинацией констант O_APPEND (добавить данные к концу файла), O_CREAT (создать новый файл), O_TRUNC (переписать существующий файл), O_EXCL (вместе с O_CREAT запрещает повторное создание существующего файла), O_BINARY (открыть в двоичном режиме), O_TEXT (открыть как текст). Третий параметр устанавливается, если второй параметр имеет значение O_CREAT. Значение третьего параметра может быть следующим: S_IWRITE (разрешена запись в файл), S_IREAD (разрешено чтение из файла) или S_IWRITE | S_IREAD (разрешены чтение и запись). Заголовочные файлы: fcntl.h, sys\stat.h, io.h.
int close (<дескриптор файла>);
Закрывает открытый файл. В случае успеха возвращает 0, при ошибке возвращает -1.
int creat (<имя файла>,<доступ>);
Создает новый файл. В случае успеха возвращает дескриптор файла. В случае ошибки возвращает -1. Второй параметр может иметь одно из следующих значений: S_IWRITE (разрешена запись в файл), S_IREAD (разрешено чтение из файла) или S_IWRITE | S_IREAD (разрешены чтение и запись). Заголовочные файлы: sys\stat.h, io.h.
int read (<дескриптор файла>,<указатель на буфер>,<число читаемых байтов>);
Читает указанное число байтов из файла. Возвращает число байтов, являющихся содержимым файла и реально записанных в буфер. При достижении конца файла возвращается значение 0. Буфер должен иметь достаточный размер.
int write (<дескриптор файла>,<указатель на буфер>,<число записываемых байтов>);
Записывает указанное количество байтов в файл. Возвращает число байтов, реально записанных в файл. В случае, когда дисковое пространство частично недоступно, будет возвращено значение меньшее, чем указано в функции.
long lseek (<дескриптор файла>,<смещение в байтах>,<начальная позиция>);
Изменяет положение файлового указателя. В случае успеха возвращает новую позицию указателя как смещение в байтах относительно начала файла. В случае ошибки возвращает -1. Третий параметр задает точку отсчета: SEEK_SET (отсчет идет от начала файла), SEEK_CUR (отсчет идет от текущего положения указателя файла), SEEK_END (отсчет идет от конца файла).
long filelength (<дескриптор файла>);
Возвращает размер файла в байтах или -1 в случае ошибки.
int eof (<дескриптор файла>);
Определяет достижение конца файла. Возвращает истину (1), если указатель находится в конце файла и ложь (0) в противном случае.

    Приведем пример использования функций низкоуровневого ввода/вывода. Программа копирует файл s1 в файл s2 через буфер buf[NBYTES], где NBYTES - размер буфера.

#include <io.h>
#include <fcntl.h>
#include <iostream.h>
#include <sys\stat.h>
#define NBYTES 128
void main ()
{
    int fd1,fd2;
    int n_read,n_write;
    char buf[NBYTES];
    char s1[20],s2[20];
    /* --------------- */
    cout << "Имя файла-источника: ";
    cin >> s1;
    cout << "Имя файла-приемника: ";
    cin >> s2;
    fd2 =creat (s2, S_IWRITE | S_IREAD);
    fd1 = open (s1, O_RDONLY);
    cout << "Содержимое исходного файла:" << endl;
    while (!eof(fd1))
    {
         /*Читаем заданное количество байтов в буфер.*/
	 n_read = read (fd1,buf,NBYTES);
         /*Выводим их на экран.*/
	 for(int i=0;i< n_read;i++)  cout << buf[i];
         /*Записываем прочитанные байты в файл-приемник.*/
	 n_write = write (fd2,buf, n_read);
    }
    cout<< "\n Содержимое результирующего файла:" << endl;
    /*Перемещаем указатель файла-приемника на начало.*/
    lseek(fd2,0,SEEK_SET);
    while (!eof(fd2))  /*Выводим содержимое файла.*/
    {
	 n_read = read (fd2,buf,NBYTES);
	 for(int i=0;i< n_read;i++)  cout << buf[i];
    }
}
Текст этой программы можно взять здесь.

    На следующем шаге мы разберем вопросы, связанные с переназначением ввода/вывода.


Предыдущий шаг Содержание Следующий шаг