Чтение онлайн

на главную - закладки

Жанры

Шрифт:

Преобразование длинного пути в короткий приводится в листинге 4.17.

...

Листинг 4.17.

Преобразование пути из длинной в короткую форму

function LongPathToShort(path: String): String;

var

buffer: String;

len: Integer;

begin

SetLength(buffer, MAX_PATH);

len := GetShortPathName(PAnsiChar(path), PAnsiChar(buffer),

MAX_PATH);

SetLength(buffer, len);

LongPathToShort := buffer;

end;

Соответственно, обратное преобразование пути может выглядеть следующим образом (листинг 4.18).

...

Листинг 4.18.

Преобразование

пути из короткой в длинную форму

function ShortPathToLong(path: String): String;

var

buffer: String;

len: Integer;

begin

SetLength(buffer, MAX_PATH);

len := GetLongPathName(PAnsiChar(path), PAnsiChar(buffer),

MAX_PATH);

SetLength(buffer, len);

ShortPathToLong := buffer;

end;

При тестировании последнего листинга в Delphi 7 выяснилось, что API-функция GetLongPathName объявлена в модуле Windows. Возможно, в более старых или новых версиях Delphi это не так. Но в любом случае импортировать эту функцию из библиотеки Kernel32. dll предельно просто, достаточно поместить в модуль следующую строку:

...

function GetLongPathName(lpszLongPath: PChar;

lpszShortPath: PChar; cchBuffer: DWORD): DWORD;

stdcall; external kernel32 name \'GetLongPathNameA\

Преобразование абсолютного пути в относительный и наоборот

Теперь пришла очередь рассмотреть реализацию преобразований между абсолютной и относительной формами путей. Однако сначала рассмотрим небольшую, но полезную процедуру, используемую при преобразованиях. Процедура GetPathElements (листинг 4.19) формирует список строк из компонентов переданного ей пути (имен каталогов и имени целевого файла или каталога).

...

Листинг 4.19.

Разбиение пути на составляющие

procedure GetPathElements(path: String; elements: TStrings);

var

start, pos: Integer;

begin

start := 1;

for pos := 1 to Length(path) do

if path[pos] = \'\\' then

begin

if start <> pos then

//Выделим имя каталога

elements.Add(Copy(path, start, pos – start))

else

//Сочетание типа \'\\\' в середине пути пропускаем

;

start := pos + 1;

end;

pos := Length(path) + 1;

if start <> pos then

//Выделим имя последнего каталога или файла

elements.Add(Copy(path, start, pos – start));

end;

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

Функция преобразования абсолютного пути в относительный (от заданной в параметре curdir папки) приводится в листинге 4.20.

...

Листинг 4.20.

Преобразование абсолютного пути в относительный

function AbsPathToRelative(path, curdir: String): String;

var

pathElements, curElements: TStrings;

outPath: String;

i, j: Integer;

begin

if Copy(path, 1, 2) <> Copy(curdir, 1, 2) then

begin

//Папки на разных дисках

AbsPathToRelative := path;

Exit;

end;

//Получение составляющих абсолютного и текущего пути

pathElements := TStringList.Create;

GetPathElements(path, pathElements);

curElements := TStringList.Create;

GetPathElements(curdir, curElements);

//Пропускаем одинаковые папки

i := 0;

while (i < curElements.Count) and (i < pathElements.Count)

and (CompareText(curElements[i], pathElements[i]) = 0) do Inc(i);

//Добавляем небходимое количество переходов вверх для того,

//чтобы из папки curdir попасть в общую для path и curdir папку

for j := i to curElements.Count-1 do

outPath := outPath + \'..\\

//Заходим из папки полученной (общей) папки в папку path

for j := i to pathElements.Count – 2 do

outPath := outPath + pathElements[j] + \'\\

//Последним добавляем имя конечной папки

или файла

AbsPathToRelative := outPath + pathElements[pathElements.Count – 1];

//Списки строк больше не нужны

pathElements.Free;

curElements.Free;

end;

При преобразовании нужно учитывать, что пути, не принадлежащие одной иерархии (например, локальный и сетевой или пути, принадлежащие разным дискам, не могут быть представлены один относительно другого: у них нет общего родительского каталога.

Обратное преобразование относительного пути в абсолютный приведено в листинге 4.21. Здесь нужно отметить, что если путь папки curdir относительный, то в итоге получим также относительный путь (только относительно другой папки). Поэтому функция и называется RelativePathToRelative, а не RelativePathToAbs.

...

Листинг 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 – атрибут каталога (атрибут нельзя самостоятельно снять или назначить);

Поделиться:
Популярные книги

Жена проклятого некроманта

Рахманова Диана
Фантастика:
фэнтези
6.60
рейтинг книги
Жена проклятого некроманта

Сын Тишайшего

Яманов Александр
1. Царь Федя
Фантастика:
попаданцы
альтернативная история
фэнтези
5.20
рейтинг книги
Сын Тишайшего

Демон

Парсиев Дмитрий
2. История одного эволюционера
Фантастика:
рпг
постапокалипсис
5.00
рейтинг книги
Демон

30 сребреников

Распопов Дмитрий Викторович
1. 30 сребреников
Фантастика:
попаданцы
альтернативная история
фэнтези
фантастика: прочее
5.00
рейтинг книги
30 сребреников

Небо в огне. Штурмовик из будущего

Политов Дмитрий Валерьевич
Военно-историческая фантастика
Фантастика:
боевая фантастика
7.42
рейтинг книги
Небо в огне. Штурмовик из будущего

Осознание. Пятый пояс

Игнатов Михаил Павлович
14. Путь
Фантастика:
героическая фантастика
5.00
рейтинг книги
Осознание. Пятый пояс

Камень

Минин Станислав
1. Камень
Фантастика:
боевая фантастика
6.80
рейтинг книги
Камень

Блокада. Знаменитый роман-эпопея в одном томе

Чаковский Александр Борисович
Проза:
военная проза
7.00
рейтинг книги
Блокада. Знаменитый роман-эпопея в одном томе

Цикл "Отмороженный". Компиляция. Книги 1-14

Гарцевич Евгений Александрович
Отмороженный
Фантастика:
боевая фантастика
рпг
постапокалипсис
5.00
рейтинг книги
Цикл Отмороженный. Компиляция. Книги 1-14

Книга 4. Игра Кота

Прокофьев Роман Юрьевич
4. ОДИН ИЗ СЕМИ
Фантастика:
фэнтези
боевая фантастика
рпг
6.68
рейтинг книги
Книга 4. Игра Кота

Мастер 2

Чащин Валерий
2. Мастер
Фантастика:
фэнтези
городское фэнтези
попаданцы
технофэнтези
4.50
рейтинг книги
Мастер 2

Новый Рал 2

Северный Лис
2. Рал!
Фантастика:
фэнтези
7.62
рейтинг книги
Новый Рал 2

Низший 2

Михайлов Дем Алексеевич
2. Низший!
Фантастика:
боевая фантастика
7.07
рейтинг книги
Низший 2

Под маской, или Страшилка в академии магии

Цвик Катерина Александровна
Фантастика:
юмористическая фантастика
7.78
рейтинг книги
Под маской, или Страшилка в академии магии