Листинг 4.21.
Преобразование относительного пути в абсолютный
function RelativePathToRelative(path, curdir: String): String;
var
pathElements, curElements: TStrings;
outPath: String;
i: Integer;
begin
//Получение списка составляющих абсолютного и текущего пути
pathElements := TStringList.Create;
GetPathElements(path, pathElements);
curElements := TStringList.Create;
GetPathElements(curdir, curElements);
//Изначально находимся в последней папке пути curdir
//"Путешествуем" от текущей папки вверх или вниз
//по дереву каталогов
//(прибавляя или удаляя компоненты пути в список curElements)
for i := 0 to pathElements.Count–1 do
begin
if pathElements[i] = \'..\' then
//Вверх по дереву
if (curElements.Count > 0)then
curElements.Delete(curElements.Count – 1)
else
curElements.Append(\'..\')
else if pathElements[i] <> \'.\' then
//Вниз по дереву (знак текущей папки "." не изменяет
//положение)
curElements.Append(pathElements[i]);
end;
//Формируем результирующий путь
if (curElements.Count > 0) then outPath := curElements[0];
for i := 1 to curElements.Count-1 do
outPath := outPath + \'\\' + curElements[i];
RelativePathToRelative := outPath;
//Списки строк больше не нужны
pathElements.Free;
curElements.Free;
end;
Поиск
Поиск является неотъемлемой частью работы с файловой системой. Даже простой просмотр содержимого любого каталога сопряжен с использованием простейших, но все-таки поисковых средств (перебор и, возможно, отсеивание элементов каталога). Поэтому далее мы рассмотрим возможные варианты реализации двух удобных функций поиска: поиск по маске и атрибутам файлов в пределах заданной папки и такой же поиск по всему дереву каталогов, начиная от заданной корневой папки. Все рассмотренные далее функции поиска можно найти в модуле Search, расположенном на диске, в папке с названием подраздела.
Но сначала немного сведений о масках для поиска и атрибутах файлов (и папок).
Маски и атрибуты
Маска имени файла или папки представляет собой строку, в которой неизвестный одиночный символ можно менять на? а произвольное количество (0 и более) неизвестных заранее символов – на *. Остальные (допустимые в имени) символы обозначают сами себя. Например, имена файлов SomeFile. ехе и Some. ехе удовлетворяют каждой из масок: Some* и Some*. ехе.
Атрибуты определяют некоторые важные особенности файла. Так, например, при просмотре каталога при помощи API-функций папка может отличаться от файла только наличием атрибута FILE_ATTRIBURE_DIRECTORY. Вообще содержимое папки (директории, каталога) записано на диске в самый обычный файл. Его отличает наличие указанного неизменяемого вручную атрибута и строго заданный формат записей, а также наличие специальных функций, скрывающих от нас все особенности работы с данными каталога (открытие файла, поиск нужных записей).
Итак, далее об атрибутах. Ниже приводится перечень наиболее часто используемых атрибутов файлов и каталогов (идентификаторы целочисленных констант, объявленных в модуле Windows). Если не сказано иное, атрибут можно изменить.
• FILE_ATTRIBUTE_ARCHIVE – архивный файл или каталог (на опыте замечено, что этот атрибут появляется практически у всех файлов, находящихся на диске некоторое время);
• FILE_ATTRIBUTE_DIRECTORY – атрибут каталога (атрибут нельзя самостоятельно снять или назначить);
• FILE_ATTRIBUTE_HIDDEN – скрытый файл или каталог;
• FILE_ATTRIBUTE_NORMAL – означает отсутствие особых атрибутов у файла или каталога (у последнего, естественно, всегда установлен атрибут FILE_ ATTRIBUTE_DIRECTORY);
• FILE_ATTRIBUTE_READONLY – файл или каталог только для чтения;
• FILE_ATTRIBUTE_SYSTEM – системный файл или каталог;
• FILE_ATTRIBUTE_TEMPORARY – временный файл (файловая система стремится по возможности хранить все содержимое открытого временного файла в памяти для ускорения доступа к находящимся в нем данным).
Были рассмотрены основные атрибуты, которые могут быть присвоены объектам файловой системы (файлам и папкам), но не было сказано, как получить или установить атрибуты файла или каталога. Атрибуты можно получить при просмотре содержимого каталога (как в рассмотренных далее функциях поиска). А можно использовать для этого API-функцию GetFileAttributes. Она принимает путь файла (PChar) и возвращает значение типа DWORD (32-битное целое значение), представляющее собой битовую маску. Если функция GetFileAttributes завершается неудачно, то возвращаемое значение равно $FFFFFFFF (-1 при переводе к беззнаковому целому).
Каждому из рассмотренных атрибутов соответствует бит в возвращаемом функцией GetFileAttributes значении. Вот отрывок программы, определяющей, является ли файл системным: