Относительное зло или когда пути неисповедимы
Запись от Rius размещена 03.08.2018 в 08:24
Показов 34778
Комментарии 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
Комментарии
-
Запись от Usaga размещена 03.08.2018 в 09:08
-
Это уже есть в FAQ. Правда в более кратком изложении - https://www.cyberforum.ru/csha... ost8862983
Сообщение от Usaga
Если у Rius есть желание выложить это в виде темы, то я перенесу её в прикрепленную тему по IO
https://www.cyberforum.ru/csha... 63620.htmlЗапись от OwenGlendower размещена 03.08.2018 в 10:11
-
Запись от Rius размещена 03.08.2018 в 10:25
-
Это слишком категоричный совет, если смотреть на него глобально. Многие могут понять его неправильно. При проектировании внутренней инфраструктуры программы все файлы должны описываться относительными путями, которые приклеиваются к некому базовому пути, который уже является абсолютным и вычисляется/настраивается один раз при старте программыЗапись от Evg размещена 03.08.2018 в 14:49
-
Запись от Rius размещена 03.08.2018 в 15:33
-
Запись от Evg размещена 03.08.2018 в 18:45
-
У меня тоже была такая проблема. В ярлыке подправил и всего делов
Запись от TopLayer размещена 03.08.2018 в 18:50
-
Запись от Rius размещена 03.08.2018 в 19:15
-
Задача заключалась в слежении за файлами определённой программы. Изначально я думал просто закинуть свой exe-шник в папку, куда установлена программа. Но когда обнаружил багу, понял, что теперь ничего никуда копировать не надо, а достаточно настроить ярлык. Короче говоря, два неверных решения уравновесили друг друга. Или это всё равно костыльно?
Сообщение от Rius
Запись от TopLayer размещена 04.08.2018 в 18:26
-
Сами вот эти параметры совместимости со старыми приложениями, что настраиваются в ярлыках, являются костылями, призванными подпереть работу в новых ОС тех программ, что с неё работать нормально не умеют.
У вас всё совпало, что никто никому не мешает, повезло.
Но могло быть такое, что та определённая программа для своих нужд могла попытаться удалить или переименовать свой каталог (для обновления, например). И наличие другого процесса, имеющего current directory настроенным на этот каталог, заблокировало бы эту операцию. Вот такая не очевидная фича у Windows есть.Запись от Rius размещена 04.08.2018 в 19:17
-
Запись от Storm23 размещена 26.08.2018 в 11:15
-
Да.
Применительно к .Net Framework этот баг можно вернуть:
Кликните здесь для просмотра всего текстаC# 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
private void button1_Click(object sender, EventArgs e) { using (var dialog = new OpenFileDialog()) { dialog.AutoUpgradeEnabled = false; dialog.RestoreDirectory = false; // Как только открылся диалог, в соседнем обработчике таймера вылетит исключение. if (dialog.ShowDialog() == DialogResult.OK) { } } } private void timer1_Tick(object sender, EventArgs e) { this.textBox1.AppendText(Directory.GetCurrentDirectory()); try { string content = File.ReadAllText("TextFile1.txt"); this.textBox1.AppendText(content); } catch(Exception exc) { this.textBox1.AppendText(exc.Message); } }
Ещё одна причина не полагаться на относительные пути.Запись от Rius размещена 26.08.2018 в 11:31
-
Запись от Agregat размещена 26.08.2018 в 17:00
-
Это не внезапно, это очевидно. И это даже не баг, а скорее фича, можно одну и туже программу запускать из разных директорий с разными настройками с помощью бат-файлов или ярлыков.
Это неправильный подход, вызванный недостатком знаний.
Если не ошибаюсь это нужно лишь при работе с программами MS Word /Excel в остальных случаях это лишь лишние телодвижения.
Если не подводит память это кажется настраивается в самом компоненте.
Но да программа может поменять текущую директорию налету сама через SetCurrentDirectory(), но по очевидным причинам так не принято делать.Запись от Avazart размещена 26.08.2018 в 18:23
-
Avazart эта фича очевидна для тех, кто умеет работать с консолью.
Внезапно натыкающиеся на это явление, темы которых перечислены в начале, к таковым не относятся. Они ошибочно полагают, что Current Directory это просто тот каталог, где лежит программа. А это, внезапно для них, оказывается не так и программа не работает.Запись от Rius размещена 26.08.2018 в 18:29
-
Запись от Avazart размещена 26.08.2018 в 18:43
-
Применение полного пути устраняет данную проблему вообще.
Применение относительного пути требует понимания, что такой текущий каталог, как он устанавливается и от чего может измениться. И если код или софт даже от понимающего автора, использующий относительные пути, попадёт в руки непонимающему пользователю, то он может перестать работать.
Это всё равно что утверждать, что антивирусный софт не нужен, потому что пряморукость решает. Только вот пряморукость не столь распространена, как хотелось бы.
Данная запись как раз для тех, кто не умеет. Кто умеет, ему объяснять незачем.
И опять же, те, кто интересуются истоками, на такие грабли не наступят. А кто не интересуется - попробуй заставь. Хотите - напишите статью об истории возникновения current directory.Запись от Rius размещена 26.08.2018 в 19:00
-
Какую проблему? Недостатка ума/знаний?
Не думаю.
А это все равно что поощрять дураков в их невежестве и чуть ли не уступать им место в транспорте.
Ээ.. Вы предлагаете писать программы не имея даже приблизительного понятия что такое ОС ?
Это не история это азы ОС да и можно погуглить https://ru.wikipedia.org/wiki/... 0%BE%D0%B3
Т.е это понятие не только для винды существует.Запись от Avazart размещена 26.08.2018 в 19:04
-
Да хотя бы упомянутую Storm23:
Кликните здесь для просмотра всего текста
Вы хотите каждого новичка- научиться пользоваться консолью
- понимать
- что такое current directory;
- откуда оно возникло;
- как устанавливать и получать;
- как оно может измениться без нашего участия;
- как с этим правильно работать?
Так займитесь ими самостоятельно. Всё в ваших руках. Не надо мне это внушать, внушайте новичкам.Запись от Rius размещена 26.08.2018 в 19:18
-
Нет такой проблемы ибо XP мертва.
Этого
Достаточно и само собой разумеется.
Большая часть книг начинают обучение именно с написания консольных приложений.
Касательно рабочего каталога нужно только погуглить и прочитать пару строчек:
https://ru.wikipedia.org/wiki/... 0%BE%D0%B3Запись от Avazart размещена 26.08.2018 в 19:22



