Установка размера файла, инициализация файла и разреженные файлы
Функция SetEndOfFile позволяет переустановить размер файла, используя текущее значение указателя файла для определения его размера. Возможно как расширение, так и усечение файла. В случае расширения файла содержимое области расширения не определено. Файл будет фактически потреблять выделенные квоты дискового и пользовательского пространств, если только не является разреженным. Файлы можно сжимать с целью уменьшения объема занимаемого ими пространства. Этот вопрос исследуется в упражнении 3.1.
Функция SetEndOfFile устанавливает физический конец файла. Прежде чем выполнять эту операцию, на которую может уйти довольно длительное время, необходимое для записи данных файл с целью его заполнения, можно установить также логический конец файла, используя для этого функцию SetValidFileData. Эта функция определяет ту часть файла, которая, в соответствии с вашими предположениями, в настоящий момент содержит достоверные данные, благодаря чему вы сможете сэкономить время при установке физического конца файла. Часть файла, заключенная между его логическим и физическим концами, называется хвостовиком (tail) и может быть сокращена путем записи оставшихся данных после логического конца файла или в результате дополнительного вызова функции SetValidFileData.
В случае разреженных файлов (sparse files), появившихся в Windows 2000, дисковое пространство расходуется лишь по мере записи данных. Администратор может назначать, какие файлы, каталоги или тома должны быть разреженными. Кроме того, можно назначить существующий файл в качестве разреженного с помощью функции DeviceIoControl, если установить при ее вызове флаг FSCTL_SET_SPARSE. Ситуацию, в которой удобно использовать разреженные файлы, иллюстрирует программа 3.1. К разреженным файлам функция SetValidFileData неприменима.
Файлы FAT нулями автоматически не инициализируются. Согласно документации Microsoft содержимое вновь созданных файлов не определено, что подтверждается экспериментами. Поэтому, если для корректной работы требуется инициализация файлов, приложения должны это делать самостоятельно путем вызова функции WriteFile. Файлы NTFS будут инициализированы, поскольку уровень безопасности С2, обеспечиваемый Windows, требует, чтобы чтение содержимого удаленных файлов было невозможным.
Обратите внимание, что кроме функции SetEndOfFile существуют и другие способы расширения размера файла. Так, можно расширить файл, используя ряд последовательных операций записи, хотя при этом существует риск увеличения степени фрагментации файла; размещение на диске файлов в виде непрерывных блоков большого размера функция SetEndOfFile отдает на откуп операционной системе.
Пример: обновление записей, находящихся в произвольном месте файла
Программа RecordAccess (программа 3.1) обеспечивает поддержку файлов фиксированного размера, состоящих из записей фиксированного размера. В заголовке файла хранится количество непустых записей, содержащихся в файле, а также емкость файла. Пользователю предоставляется возможность выполнять в интерактивном режиме чтение, запись (обновление) и удаление записей, каждая из которых содержит метки времени, текстовую строку и счетчик, показывающий, сколько раз запись изменялась. В качестве несложного и реалистичного расширения возможностей программы можно было бы добавить в структуру записи ключ и определять местоположение записей в файле путем применения хэш-функции к значениям ключа.
Программа демонстрирует позиционирование указателя файла перед заданной записью, а также выполнение 64-битовых арифметических операций с использованием данных типа LARGE_INTEGER Microsoft С. Чтобы проиллюстрировать логику работы указателей файла, в программу включен код, проверяющий наличие ошибок. Программа в целом иллюстрирует применение файловых указателей и множественных структур OVERLAPPED, а также обновление файлов с использованием 64-битовых файловых указателей.
Общее количество записей в файле указывается в командной строке; при большом количестве записей размеры создаваемых файлов могут быть очень большими и даже гигантскими, поскольку длина одной записи составляет примерно 300 байт. После выполнения нескольких экспериментов вы убедитесь, что большие файлы должны быть разреженным; в противном случае необходимо размещать и инициализировать на диске весь файл целиком, в результате чего может существенно увеличиться время обработки файла и занимаемое им место на диске. Хотя в листинге программы 3.1 это и не отражено, в программе предусмотрен участок кода, обеспечивающий создание разреженных файлов, если в этом возникает необходимость; в некоторых системах, например Windows XP Home, этот код правильно работать не сможет.
На Web-сайте книги предоставляются три дополнительные программы, родственные этой: tail.с — другой пример реализации произвольного доступа к файлу, getn.c — упрощенная версия программы RecordAccess, обеспечивающая лишь чтение записей, и atouMT (включена в программы для главы 14, находящиеся на Web-сайте, однако не включена в программы, приведенные в книге), также иллюстрирующая прямой доступ к файлам.