Работа с файлами, каталогами и томами в Windows API




Файловая система

 

Для работы с файлами в Windows содержится свой набор функций, позволяющих выполнять основные операции над файлами. В первых 16ти разрядных версиях Windows (по 3.x включительно) эти функции основывались на применении функций MS–DOS. Непосредственно в Windows описан только минимальный набор базовых функций, для выполнения других операций всегда можно воспользоваться прерыванием 0x21. В отличие от них, 32х разрядные версии Windows содержат уже полный набор функций для работы с файлами, при этом использование функций MS–DOS не допускается. Функции Win32 API для работы с файлами — это расширенный набор функций по сравнению с Windows API.

 

Работа с файлами, каталогами и томами в Windows API

 

В Windows 3.x применяется файловая система MS–DOS. В первых версиях Windows вообще вся работа с дисками просто переадресовывалась к функциям MS–DOS, в поздних версиях, например Windows for Workgroup 3.11, в частных случаях может использовать собственные средства, реализующие доступ к диску и к файлам в 32х разрядном защищенном режиме. Это несколько увеличивает производительность системы, работающей в защищенном режиме, так как при обращениям к данным на диске исключаются переключения процессора из защищенного режима в реальный и обратно. При этом система проверяет, возможно ли с помощью имеющихся драйверов обращаться к данному диску, или нет. Если это невозможно (например, используются нестандартные DOS–драйверы), то для доступа к диску и файлам применяются средства MS–DOS, как в предыдущих версиях Windows.

Файлы (file) группируются в каталоги (directory или folder, папки). В одном каталоге может находиться большое количество файлов или других вложенных каталогов. Каталоги образуют строго древовидную структуру — данный каталог может содержать сколько угодно вложенных, но сам он может быть вложен только в один родительский каталог (каталог верхнего уровня). На каждом томе (volume) существует один каталог самого верхнего уровня — корневой каталог (root directory). Для обозначения конкретного тома используются буквы английского алфавита, начиная с “a”.

Имена файлов (file name) и каталогов (directory name, folder name) в Windows API, как и в MS–DOS, состоят из имени, длиной до 8 символов и расширения, длиной до 3 символов, отделяемого от имени одной точкой. Таким образом максимальная длина имени составляет 12 символов, включая разделяющую точку. Для точного задания файла необходимо указать не только его имя, но также и каталог, в котором он находится. Причем, так как каталоги могут быть вложенные, то необходимо задавать список каталогов, которые надо пройти на пути от текущего каталога, либо от корневого каталога тома до каталога, содержащего нужный файл.

Имя тома, путь до файла и имя файла составляют так называемое полное имя файла (path name). Полное имя начинается с названия тома, за которым следует двоеточие, обратная косая черта и список каталогов на пути к файлу, разделяемых обратными косыми чертами, затем следует имя файла и его расширение, отделяемое точкой. Например: E:\Mka\Book\Samples\1a.cpp

Указывает на файл 1a.cpp, находящийся к каталоге Samples, вложенном в подкаталог Book и, вместе с ним, в подкаталог Mka, хранящийся на томе E.

Для каждого тома существует понятие текущего каталога (current directory). Кроме того существует понятие текущего тома (диска) (current drive). Для задания файла, находящегося в текущем каталоге текущего тома, достаточно просто указать имя этого файла. Вы можете легко сделать текущий диск другим и перейти в нем в какой–либо иной каталог. В этом случае система запомнит тот каталог, в котором вы были перед переходом на другой диск, и будет считать его текущим каталогом для прежнего диска.

Так, например:

1a.cpp — задает файл 1a.cpp в текущем каталоге текущего диска

E:1a.cpp — задает файл 1a.cpp в текущем каталоге тома E

E:\1a.cpp — задает файл 1a.cpp в корневом каталоге тома E

\1a.cpp — задает файл 1a.cpp в корневом каталоге текущего диска

Система допускает использование специальных имен “.” (точка) и “..” (две точки) для задания текущего каталога и для задания каталога верхнего уровня. Например, пусть текущий каталог E:\Mka\Book\Samples, тогда:

.\1a.doc — задает файл E:\Mka\Book\Samples\1a.cpp

..\Chapter2.doc — задает файл E:\Mka\Book\Chapter2.doc

В системе запрещается использовать имена файлов и каталогов, совпадающие с именами стандартных устройств, например CON, COM2, LPT1, PRN и так далее.

Система ограничивает максимальную длину полного имени файла 144 символами. Так как заранее известно, что полное имя не превысит этой длины, то часто для работы с именами файлов используются статически выделяемые области, размер которых не изменяется.

Собственно в Windows 3.x содержится небольшой набор функций, повторяющих основные операции над файлами — создание, открытие, позиционирование файлового указателя, чтение, запись и закрытие; помимо этого предусмотрено несколько дополнительных функций. Функций для разделения доступа, переименования или копирования файлов, создания и смены каталогов и прочего не предусматривается. При необходимости можно воспользоваться прерыванием 0x21, либо функциями стандартной C–библиотеки времени выполнения.

HFILE _lcreat(lpszFilename, fnAttribute);

HFILE _lopen(lpszFilename, fnOpenMode);

LONG _llseek(hf, lOffset, nOrigin);

UINT _lread(hf, hpvBuffer, cbBuffer);

UINT _lwrite(hf, hpvBuffer, cbBuffer);

long _hread(hf, hpvBuffer, cbBuffer);

long _hwrite(hf, hpvBuffer, cbBuffer);

HFILE _lclose(hf);

Назначение этих функций понятно из названия. Среди них интересны только две процедуры — _hread и _hwrite — которые предназначены для чтения и записи больших фрагментов файлов за одну операцию. Под большими в данном случае понимаются фрагменты, превышающие 65535 байт (64K), то есть превышающие размер одного 16ти разрядного сегмента. Для 16ти разрядной платформы Windows 3.x это очень удобно.

Неудобным в функциях Windows API для работы с файлами является то, что для флагов этих функций предусмотрены только числовые значения, а не символические. Так, например, для функции _lcreat параметр fnAttribute равный 0, соответствует созданию обычного файла, а 2 — скрытого. Или для функции _llseek параметр nOrigin равный 1 указывает на задание нового положения относительно текущего, а не относительно начала файла. Все эти константы так и надо указывать в виде числа, предварительно проверив их значение по руководству.

Используемые в Windows хендлы файлов являются хендлами файлов MS–DOS. Это позволяет легко применять обычные средства для работы с файлами. С другой стороны это приводит к типичной ошибке: в Windows принято, что значение 0 для хендла является недопустимым; то есть обычная проверка при получение хендла какого–либо объекта выглядит так:

HANDLE hObject;

hObject = Get...(...); // получаем хендл объекта

if (hObject) {// проверяем его...

// все в порядке

} else {

// ошибка!}

Однако при работе с файлами такой способ ошибочен — хендл файла, равный 0, в MS–DOS соответствует стандартному устройству для вывода (stdout), а не недопустимому. Для обозначения ошибки применяется значение хендла файла не 0, а -1. Для удобства в windows.h определен специальный символ HFILE_ERROR, равный -1. Предыдущий фрагмент при работе с файлами должен выглядеть так:

HFILE hFile;

hFile = _lcreat(“c:\\myfile.dat”, 0);

if (hFile!= HFILE_ERROR) {

// все в порядке

...

_lclose(hFile);

} else {

// ошибка!}

Помимо уже рассмотренных в Windows предусмотрена специальная функция, предназначенная для открытия, поиска, удаления файлов и выполнения некоторых других операций:

HFILE OpenFile(lpszFileName, lpOpenBuff, fuMode);

Параметр lpOpenBuf является указателем на структуру OFSTRUCT. В этой структуре сохраняется информация об открытом файле, что позволяет использовать ее для повторного открытия (или удаления) того–же файла позже. Параметр fuMode обычно указывает режим доступа к открытому файлу (флаги OF_READ, OF_WRITE, OF_READWRITE), выполняемую операцию — открыть или создать файл (OF_CREATE), ограничение доступа к файлу других приложений (OF_SHARE_...).

Помимо открытия файла данная функция способна выполнять некоторые специфические операции (задаваемые тем–же параметром fuMode):

удаление файла OF_DELETE,

поиск файла OF_SEARCH,

проверка существования файла OF_EXIST,

повторное открытие файла по информации, сохраненной в структуре OFSTRUCT OF_REOPEN,

инициализацию структуры OFSTRUCT OF_PARSE,

сравнение даты и времени создания файла с данными в структуре OFSTRUCT OF_VERIFY,

а также сообщать о невозможности открыть файл (при этом функция OF_PROMPT и не позволяет ни выбрать другой файл, ни указать новое имя файла) OF_CANCEL

Еще несколько функций Windows носят вспомогательный характер. Так, например, функции GetWindowsDirectory и GetSystemDirectory возвращают информацию о каталоге, содержащем win.com — каталоге Windows и системном каталоге (обычно windows\system).

UINT GetWindowsDirectory(lpszSysPath, cbSysPath)

UINT GetSystemDirectory(lpszSysPath, cbSysPath);

Интересно, что Windows не предоставляет функции для получения текущего каталога — для этого надо использовать либо функции стандартной библиотеки, либо можно узнать полный путь к выполняемому файлу, а из него выделить путь (в некоторых случаях даже важнее знать именно каталог, в котором находится исполняемый модуль, чем текущий):

Int GetModuleFileName(hInstance, lpszFileName, cbFileName);

Еще пара функций помогает создавать временные файлы. Функция GetTempDrive возвращает букву, обозначающую диск, используемый для хранения временных файлов (при этом параметр функции chDriveLetter не используется). При этом предполагается, что для хранения временных файлов используется первый жесткий диск (обычно C), а если он не существует, то текущий диск. Вторая функция — GetTempFileName помогает построить уникальное имя временного файла, при этом она использует либо переменную окружения TEMP, либо, если она не определена, то корневой каталог указанного тома, либо, если он не задан, корневой каталог первого жесткого диска (обычно C).

BYTE GetTempDrive(chDriveLetter);

Int GetTempFileName(chDriveLetter, lpszPrefixString, uUnique, lpszTempFileName);

Однако эти функции нужны только для формирования уникального имени для временного файла. Собственно временным этот файл не будет — для его удаления после закрытия надо использовать соответствующую функцию, система за вас этого не сделает.

Функция SetHandleCount позволяет изменить максимально допустимое число одновременно открываемых файлов одним приложением. По умолчанию одно приложение может открыть до 20 файлов сразу.

UINT SetHandleCount(cHandles);

Последняя функция возвращает информацию о типе дискового устройства. К сожалению эта информация крайне скудна — Windows распознает только три вида дисковых устройств: фиксированные (DRIVE_FIXED), сменные (DRIVE_REMOVABLE) и удаленные (DRIVE_REMOTE):

UINT GetDriveType(nDriveNumber);

Параметр nDriveNumber задает номер диска: устройство “A” имеет номер 0, “C” — 2 и так далее. Возвращаемое функцией значение тип диска (DRIVE_FIXED, DRIVE_REMOVABLE, DRIVE_REMOTE), либо, в случае ошибки, 0.

 




Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2019-06-03 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: