На этом шаге мы рассмотрим правила и функции работы с файлами "на низком уровне".
Компьютер "рассматривает" содержимое любого файла как последовательность байтов, интерпретацию которых осуществляют функции высокоуровневого ввода/вывода. Однако в некоторых случаях эту интерпретацию должен осуществлять сам программист. Для реализации этой задачи в C++ имеются функции низкоуровневого ввода/вывода. Перечислим функции, позволяющие работать с файлами на низком уровне. Если не оговорено особо, то заголовочный файл io.h.
Открывает файл в заданном режиме. Функция возвращает дескриптор файла, который затем используется в других функциях работы с файлами. Второй параметр может принимать следующие значения (они записаны в заголовочном файле 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. | |
Закрывает открытый файл. В случае успеха возвращает 0, при ошибке возвращает -1. | |
Создает новый файл. В случае успеха возвращает дескриптор файла. В случае ошибки возвращает -1. Второй параметр может иметь одно из следующих значений: S_IWRITE (разрешена запись в файл), S_IREAD (разрешено чтение из файла) или S_IWRITE | S_IREAD (разрешены чтение и запись). Заголовочные файлы: sys\stat.h, io.h. | |
Читает указанное число байтов из файла. Возвращает число байтов, являющихся содержимым файла и реально записанных в буфер. При достижении конца файла возвращается значение 0. Буфер должен иметь достаточный размер. | |
Записывает указанное количество байтов в файл. Возвращает число байтов, реально записанных в файл. В случае, когда дисковое пространство частично недоступно, будет возвращено значение меньшее, чем указано в функции. | |
Изменяет положение файлового указателя. В случае успеха возвращает новую позицию указателя как смещение в байтах относительно начала файла. В случае ошибки возвращает -1. Третий параметр задает точку отсчета: SEEK_SET (отсчет идет от начала файла), SEEK_CUR (отсчет идет от текущего положения указателя файла), SEEK_END (отсчет идет от конца файла). | |
Возвращает размер файла в байтах или -1 в случае ошибки. | |
Определяет достижение конца файла. Возвращает истину (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]; } }
На следующем шаге мы разберем вопросы, связанные с переназначением ввода/вывода.