Глава 5. Управление файлами
Файл - важнейшая образующая практически любой программы. С появлением скоростных дисков больших объемов значение файлов сильно возросло. Использование API-функций управления файлами может сделать вашу программу более эффективной и производительной. Большинство программ данной главы являются консольными, потому что консольная программа как никакая другая подходит для демонстрации файловой обработки.
I
32-битная FAT. Характеристики файлов
Давая описание характеристикам файлов, я буду основываться на характеристиках, которыми манипулируют функции API. О типах и структуре файловых систем речь пойдет далее.
Атрибут файла. Размер - DWORD
.
FILE_ATTRIBUTE_READONLY equ 1h
Атрибут - "только чтение".
Приложения могут лишь читать данный файл. Соответственно, попытка открыть файл
для записи вызовет ошибку.FILE_ATTRIBUTE_HIDDEN equ
2h
Атрибут - "скрытый файл". "Невиден" при обычном просмотре каталога
(см. ниже, поиск файлов).FILE_ATTRIBUTE_SYSTEM equ
4h
Атрибут - "системный файл". Говорит о том, что данный файл
принадлежит операционной системе.FILE_ATTRIBUTE_DIRECTORY equ
10h
Атрибут - "директорий", С файлами с таким атрибутом операционная
система обращается особым образом, считая его каталогом, т.е. считая его списком
файлов, состоящим из записей по 32 байта.FILE_ATTRIBUTE_ARCHIVE equ
20h
Со времен MS DOS таким атрибутом отмечались файлы, над которыми не
произведена операция BACKUP или XCOPY. Для целей программирования данный атрибут
эквивалентен нулевому значению атрибута.FILE_ATTRIBUTE_NORMAL equ
80h
Данный атрибут означает, что у файла не установлены другие
атрибуты.FILE_ATTRIBUTE_TEMPORARY equ 100h
Атрибут означает,
что данный файл предназначен для временного хранения. После закрытия файла
система должна его удалить.FILE_ATTRIBUTE_COMPRESSED equ
800h
Для файла это означает, что он сжат системой; для директория -
что вновь создаваемый файл по умолчанию должен быть
сжат.FILE_ATTRIBUTE_OFFLINE equ 1000h
Данный атрибут
означает, что данные файла не доступны в данный момент.
Смену атрибута можно осуществить функцией SetFileAttributes
,
получить значение атрибута функцией GetFileAttributes
. Следует
заметить, что если операционная система не накладывает никаких ограничений на
возможности изменения атрибутов файлов, то фактически обесценивается смысл самих
атрибутов - всегда можно снять атрибут "только чтение" и делать с файлом, что
заблагорассудится.
Файл имеет три временные характеристики: время создания, время
последней модификации, время последнего доступа. Время отсчитывается в
наносекундных интервалах начиная с 12.00 по полудни 1 января 1600 года и
хранится в двух 32-битных величинах. Надо сказать, что время хранится в так
называемых универсальных координатах и должно еще быть преобразовано в локальное
время (функция FileTimeToLocalFileTime
). Получить значение всех
трех времен можно функцией GetFileTime
.
Длина файла в байтах хранится обычно в двух 32-битных величинах либо в
одной 64-битной величине. Если 32-битные величины обозначить как l1 (младшая
часть) и l2 (старшая часть), то 64-битная величина выразится формулой
l2*0FFFFH+l1. Paзмер файла можно получить функцией GetFileSize
.
Кроме указанных характеристик, файл, разумеется, имеет имя. При этом
мы будем различать длинное и короткое имя. Точно также будем различать полный
путь (со всеми длинными именами) и укороченный путь (все длинные имена заменены
укороченными). Необходимость использования укороченного имени и пути диктуется,
прежде всего, тем, что некоторые программы получают путь или имя на стандартный
вход и трактуют пробелы как разделители для параметров. Преобразование длинного
имени в короткое можно осуществить функцией GetShortPathName
,
которая работает и для имени, и для пути. Обратное преобразование можно
осуществить функиией GetFullPathName
.
В данной книге мы не рассматриваем вопроса о прямом доступе к диску. Но вопрос о структуре записей каталога может у читателя все же возникнуть. Это и понятно, ведь с переходом к FAT3233, во-первых, появилась возможность хранения файлов с длинным именем, во-вторых, у файла, кроме времени и даты модификации, появились еще время и дата создания и доступа. Где же все это хранится?
Для того чтобы ответить на поставленный вопрос, вспомним, что каталог в
файловых системах FAT34 делится на записи
длиной 32 байта. Ниже приводится структура записи для FAT32. Пустыми записями
считаются записи, содержащие нулевые байты, либо начинающиеся с кода
E5H
(для удаленных записей). На файл с обычным именем (восемь байт
на имя и 3-на расширение) отводится 32 байта. В байте со смещением +11
содержится атрибут файла. Если атрибут файла равен 0FH
, то система
считает, что здесь содержится длинное имя. Длинное имя кодируется в UNICODE и
записывается в обратном порядке. За одной или несколькими записями с длинным
именем должна следовать запись с обычным именем, содержащим знак "~" - тильда.
Здесь содержится также остальная информация о файле. Как видите, алгоритм
просмотра каталога с выявлением информации о файле весьма прост. Обратимся
теперь к структуре записи каталога. В старой операционной системе MS DOS байты с
12 по 21 никак не использовались системой (см. [1]). Новой системе они
пригодились. Ниже в таблице дана новая структура записи каталога.
Смещение | Размер | Содержимое |
---|---|---|
(+0) | 8 | Имя файла или каталога, выровненное на левую границу и дополненное пробелами. |
(+8) | 3 | Расширение имени файла, выровненное на левую границу и дополненное пробелами. |
(+11) | 1 | Атрибут файла. |
(+12) | 2 | Время доступа. |
(+14) | 2 | Время создания. |
(+16) | 2 | Дата создания. |
(+18) | 2 | Дата доступа. |
(+20) | 2 | Два старших байта номера первого кластера файла. |
(+22) | 2 | Время модификации файла. |
(+24) | 2 | Дата модификации файла. |
(+26) | 2 | Два младших байта номера первого кластера файла. |
(+28) | 4 | Размер файла в байтах. |
Как видите, все байты 32-байтной записи каталога теперь заняты. Лишний раз
убеждаешься в первоначальной непродуманности файловой системы MS DOS, Это
касается, в частности, длины файла. Как можно заметить, на длину файла отводится
всего 4 байта. А как найти длину файла, если на нее требуется более 4 байт?
Разумеется, в этом случае следует считать, что в каталоге хранятся младшие байты
длины, а полную длину легко определить, обратившись к таблице размещения файлов.
Но, согласитесь, что это уже явная недоработка. Странно также выглядит функция
GetFileSize
, которая возвращает четыре младших байта длины файла,
старшие же байты возвращаются во втором параметре функции.
Иное дело в файловой системе NTFS, поддерживаемой Windows NT, изначально планируемой для работы с файлами больших размеров. Здесь для индексации кластеров используются 64-битные поля.
33 В начале Windows 95 работала с 16-битной FAT, но длинные имена уже поддерживала.
34 FAT (File Allocation Table) - один из элементов, на котором базируются файловые системы MS DOS и Windows 9х. По этой причине часто такие файловые системы называют FAT системами.