Относительное зло или когда пути неисповедимы
Запись от Rius размещена 03.08.2018 в 08:24
Показов 35764
Комментарии 24
Часто встречаются такие и подобные вопросы:
Что такое относительный путь? Это путь к файлу/каталогу (далее просто к файлу) в сокращённом виде, т.е. без корневого каталога или буквы диска. Например: ../file.txt или ./subdirectory/.В противоложность, есть абсолютный путь (полные) вида /etc/network/interfaces (Linux, начинается с корневого каталога) или c:\Windows\System32\drivers\etc\hosts (Windows, начинается с буквы диска).Для обращения к файлу, операционной системе требуется знать абсолютный путь. Но если путь указан относительный, системе придётся самостоятельно приводить его к абсолютному. В этом случае вступает в игру другое понятие, известное под именами current directory и другими.
При обращении из кода (нашей программы, чужой программы или функции ОС) к файлу по относительному пути, будет задействован current directory текущего процесса, чтобы получить абсолютный путь к файлу. Для упрощения, можно представлять это как конкатенацию строк - строкового значения current directory и строкового же значения относительного пути. Увидеть значение current directory можно в: Демонстрация взаимодействия относительного пути и current directory
Пусть есть 2 файла
Для демонстрации - программа more (консольная команда или утилита), принимающая путь к файлу и выводящая этот файл в консоль.Если мы находимся в каталоге R:\demo\1, т.е. current directory = R:\demo\1, программа может обратиться к файлу просто по имени, т.к. нужный файл находится в current directory:
Но если current directory не совпадает (внезапно!) с предполагаемым положением, всё идёт не так:
А вот абсолютные - продолжают работать, потому что на значение current directory они не опираются. В ходе написания программы в соответствующей среде разработки никаких проблем обычно не замечается, потому что при запуске своей программы из среды разработки автор обычно получает current directory совпадающим с каталогом, куда собирается программа. Поэтому не возникает ни единой мысли о том, что в коде с относительными путями что-то не так. А в ходе пробной эксплуатации, или при запуске иным способом, это не так расцветает во всей красе. Почему? Потому что current directory это вовсе не каталог, где находится программа (внезапно!). Это текущий (т.е. активный в данный момент) каталог для процесса. Они могут совпадать в какой-то момент времени, могут не совпадать, но это точно не одно и то же. Почему относительные пути работают также при
В этих случаях current directory тоже совпадает с каталогом, где расположена программа, и относительные пути отсчитываются относительно него. Как только запуск производится в иных условиях, каковые как раз и встречены в упомянутых вверху темах, всё тут же перестаёт работать. Решение: при обращении к файлам (в соответствующих методах), должны применяться только абсолютные пути, не относительные. Это вовсе не значит, что надо их хардкодить, а путь к файлу, расположенному рядом с исполняемым, получить невозможно. Если понадобился путь относительно каталога программы, или любого иного каталога, нужно этот относительный путь привести программно к абсолютному. Внимание: здесь говорится не об архитектуре приложения, а о том, что к моменту обращения к файлу, используемое значение пути должно быть абсолютным, чтобы никто (система или автор) не делал предположений о том, какой же именно путь надо будет применить, потому что реальность может разойтись с предположениями. Путь к каталогу программы можно получить разными способами. Примеры на C# .Net
Пример на VB .Net
Пример на C++
Пример на Delphi
Есть простые, есть посложнее. Метод не один потому, что в нетривиальных условиях простые методы могут выдавать ложный результат, а в тривиальных же условиях сложный код - избыточен. Далее полученный абсолютный путь к каталогу программы надо сложить с относительным путём к файлу, чтобы получить абсолютный путь к искомому файлу. Пример на C# .Net
Пример на VB .Net
Пример на C++
Почему, однако, можно запустить готовую программу типа notepad.exe или more.exe (что была в примере выше) без указания абсолютного пути?Потому что для поиска программ есть такая системная переменная PATH. Поиск программ производится сначала в current directory, а если там не найдена - далее в каталогах, перечисленных в этой переменной.
Также, случается наличие в путях поиска нескольких исполняемых файлов с одинаковым именем. Тогда тоже помогает указание абсолютного пути, либо модификация порядка путей в %PATH% (что может потребовать админских прав или отрицательно повлиять на другие программы). P.S. Немного об упомянутых в комментах эффектах:
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Размещено в Без категории
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Всего комментариев 24
Комментарии
-
Запись от Avazart размещена 26.08.2018 в 19:23
-
Запись от Rius размещена 27.08.2018 в 06:33
-
Предположим, разрабатывается программа, работающая с несколькими разными файлами в режиме чтения и/или записи. Разработка идет на скриптовом языке. Основной скрипт еще вызывает функции из других скриптов-библиотек. Ну и какой же каталог в любой момент времени будет текущим:
- каталог интерпретатора;
- каталог скрипта;
- каталог вызванной библиотеки;
- каталоги файлов, которые читает или в которые пишет скрипт?Запись от Agregat размещена 28.08.2018 в 09:35
-
Не что из перечисленного.
Рабочим будет каталог из которого пользователь запускает программу, по нормальному.
Пути поиска библиотек должны как-то отдельно задаваться (отдельным параметром консоли или переменной среды окружения итд.).
При чем наверное библиотеки должны как то делится стандартные/пользовательские.
Если же речь про пользовательские то логично брать папку расположения скрипта.
И тут интерпретатор может менять текущий каталог на каталог скрипта.
Т.е. когда речь идет о скриптовых языках все сложнее ибо есть интерпретатор, а есть скрипт с которым он работает.Запись от Avazart размещена 28.08.2018 в 17:15


