Разреженные файлы
Unix-системы позволяют создавать файлы, логический размер которых превышает физический. Такие файлы могут быть удобны, когда необходимо следовать отобразить какую либо незаполненную структуру данных (например, матрицу с большим количеством нулей). Наглядным примером разреженных файлов являются знакомые всем нам файлы core.dump. Рассмотрим текст программы makehole:
#include <stdio.h> #include <string.h> #define BIG_SIZE 0x1000000 int main(int argc, char * argv[]) { FILE * f; f = fopen(argv[1], "w"); if (f == NULL) { printf("Невозможно создать файл: %s", argv[1]); return 1; } fwrite(argv[1], 1, strlen(argv[1]), f); fseek(f, BIG_SIZE, SEEK_CUR); fwrite(argv[1], 1, strlen(argv[1]), f); fclose(f); }
Если скомпилировать эту программу под именем makehole и запустить makehole bighole.txt то на диске будет создан файл bighole.txt. Команда ls –al сообщит нам, что размер файла составляет чуть больше 16 мегабайт (см. значение константы BIG_SIZE в программе). Однако, с помощью команды du bighole.txt мы узнаем, что на диске этот файл занимает 24 байта. Причиной появления пропусков в открытом для записи файле стало смещение с помощью функции fseek() в область после конца файла. Выход за пределы файла с помощью fseek() – стандартный метод получения разреженных файлов. В момент вызова fseek() в нашей программе позиция записи находится в конце файла. Флаг SEEK_CUR указывает, что смещение отсчитывается от текущей позиции. Таким образом, в файле образуется пропуск, величина которого в байтах соответствует значению BIG_SIZE. При чтении пустых блоков в разреженном файле функция чтения данных будет возвращать блоки, заполненные нулями.