Листинг 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.