Перейти к содержимому

Как получить путь к файлу c

  • автор:

как передавать путь к файлу?

Если программа лежит в папке «D:Proga\Bin», то надо выйти на уровень вверх:

std::string path("..\\File\\file.txt"); 

(Двойная косая черта нужна, так как в Си одинарная такая черта обозначает управляющий символ).

Вариант, как могла бы выглядеть ваша программа:

#include #include #include int main(int argc, char* argv[]) < if (argc >1) < std::string path(argv[1]); std::ofstream fout(path); // Тут работаем с файлом >else < std::cout return 0; > 

Как получить путь к файлу c

У меня было так

#define DATA_FILE _T("C://set.ds")

Я открывал этот файл, при необходимости он создавался — и все было бы хорошо, но

#define DATA_FILE _T("C://Program Files//Internet Explorer//PLUGINS//set.ds")

И все больше файл открываться не хочет! (и не создается) Я больше ничего не менял в программе — значит виноваты эти строки. Подскажите, плиз.

03.03.06 22:54: Перенесено модератором из ‘C/C++’ — Павел Кузнецов
Re: Как правильно писать путь к файлу?

От: LuciferMoscow
Дата: 03.03.06 10:19
Оценка:

Здравствуйте, AlexDav, Вы писали:

AD>У меня было так

AD>

AD>#define DATA_FILE _T("C://set.ds") AD>

AD>Я открывал этот файл, при необходимости он создавался — и все было бы хорошо, но

AD>Я заменил на

AD>

AD>#define DATA_FILE _T("C://Program Files//Internet Explorer//PLUGINS//set.ds") AD>

AD>И все больше файл открываться не хочет! (и не создается) Я больше ничего не менял в программе — значит виноваты эти строки. Подскажите, плиз.
Попробуй путь взять в кавычки. У тебя есть пробел в пути к файлу

const TCHAR DATA_FILE[]_T("\"C://Program Files//Internet Explorer//PLUGINS//set.ds\"");

Re: Как правильно писать путь к файлу?

От: HiSH http://m0riarty.ya.ru
Дата: 03.03.06 10:21
Оценка: 2 (2)

Здравствуйте, AlexDav, Вы писали:

AD>

AD>#define DATA_FILE _T("C://set.ds") AD>

AD>Я открывал этот файл, при необходимости он создавался — и все было бы хорошо, но
AD>Я заменил на
AD>

AD>#define DATA_FILE _T("C://Program Files//Internet Explorer//PLUGINS//set.ds") AD>

AD>И все больше файл открываться не хочет! (и не создается) Я больше ничего не менял в программе — значит виноваты эти строки. Подскажите, плиз.

А зачем двойные слеши? Должно быть или «c:\\program files\\. «, или «c:/program files/. «

Re: Как правильно писать путь к файлу?

От: rg45
Дата: 03.03.06 10:24
Оценка:

Здравствуйте, AlexDav, Вы писали:

AD>У меня было так

AD>

AD>#define DATA_FILE _T("C://set.ds") AD>

AD>Я открывал этот файл, при необходимости он создавался — и все было бы хорошо, но

AD>Я заменил на

AD>

AD>#define DATA_FILE _T("C://Program Files//Internet Explorer//PLUGINS//set.ds") AD>

AD>И все больше файл открываться не хочет! (и не создается) Я больше ничего не менял в программе — значит виноваты эти строки. Подскажите, плиз.

1. Либо «C://set.ds» либо «C:/set.ds» — двойной слэш — это лишний символ в строке, хотя большинством фунций «глотается» нормально.
2. Чтобы ответить, все таки, что не так, нужно видеть, как используется эта строка.
Вполне возможно, что проблема в пробелах, которые присутствуют во втором варианте и которых нет в первом.


Не можешь достичь желаемого — пожелай достигнутого.
Re[2]: Как правильно писать путь к файлу?

От: AlexDav
Дата: 03.03.06 10:27
Оценка:

Здравствуйте, HiSH, Вы писали:

HSH>А зачем двойные слеши? Должно быть или «c:\\program files\\. «, или «c:/program files/. «

Так вот зачем эти странные палочки?! И точно работает

Re[2]: Как правильно писать путь к файлу?

От: rg45
Дата: 03.03.06 10:27
Оценка:

R>1. Либо «C://set.ds» либо «C:/set.ds» — двойной слэш — это лишний символ в строке, хотя большинством фунций «глотается» нормально.

Написал не то, что хотел, надо было так:


Не можешь достичь желаемого — пожелай достигнутого.
Re: Как правильно писать путь к файлу?

От: RevSegment
Дата: 03.03.06 10:34
Оценка:

Здравствуйте, AlexDav, Вы писали:

AD>У меня было так

AD>

AD>#define DATA_FILE _T("C://set.ds") AD>

AD>Я открывал этот файл, при необходимости он создавался — и все было бы хорошо, но

AD>Я заменил на

AD>

AD>#define DATA_FILE _T("C://Program Files//Internet Explorer//PLUGINS//set.ds") AD>

AD>И все больше файл открываться не хочет! (и не создается) Я больше ничего не менял в программе — значит виноваты эти строки. Подскажите, плиз.

А так не пробовал?
«c:\\Folder One\\Folder Two\\file.ext»

. << RSDN@Home 1.1.4 stable SR1 rev. 568>>
. опыт приходит во время боя .
Re[2]: Как правильно писать путь к файлу?

От: AlexDav
Дата: 03.03.06 10:46
Оценка:

Здравствуйте, LuciferMoscow, Вы писали:

LM>Попробуй путь взять в кавычки. У тебя есть пробел в пути к файлу
LM>

LM>const TCHAR DATA_FILE[]_T("\"C://Program Files//Internet Explorer//PLUGINS//set.ds\""); LM>

я попробовал такой путь «C:/Data/set.ds» работает — т.е. ты (можно на ты?) это пробелы, но как ты написал тоже не прокатывает?? Что Делать.

Re[3]: Как правильно писать путь к файлу?

От: ekamaloff
Дата: 03.03.06 10:50
Оценка:

Здравствуйте, AlexDav, Вы писали:

AD>я попробовал такой путь «C:/Data/set.ds» работает — т.е. ты (можно на ты?) это пробелы, но как ты написал тоже не прокатывает?? Что Делать.

Покажи где ты ее используешь и на каком варианте строки ты сейчас остановился.

It is always bad to give advices, but you will be never forgiven for a good one.
Oscar Wilde
Re[4]: Как правильно писать путь к файлу?

От: AlexDav
Дата: 03.03.06 11:07
Оценка:

Здравствуйте, ekamaloff, Вы писали:

E>Покажи где ты ее используешь и на каком варианте строки ты сейчас остановился.

Прошу прощения за MFC

#define DATA_FILE _T("\"C:\\Program Files\\Internet Explorer\\PLUGINS\\set.ds\"") . UINT nFlags = CFile::typeBinary|CFile::modeWrite; if(_waccess(DATA_FILE,0)) // надо его создать? < nFlags |= CFile::modeCreate; bCanSave = TRUE; >else < bCanSave = CanSerialize(); // всегда TRUE :) > if(bCanSave) < CFile file; CFileException fe; if(file.Open(DATA_FILE, nFlags, &fe)) // Вот и не посредственное использование < CArchive ar(&file, CArchive::store); Serialize(ar); ar.Close(); >file.Close(); >

Re[5]: Как правильно писать путь к файлу?

От: AlexDav
Дата: 03.03.06 13:35
Оценка:

Хотите верти — хотите нет, но

#define DATA_FILE _T("C:\\Program Files\\Internet Explorer\\PLUGINS\\set.dln")

просто начала работать и все! Зуб даю кроме этой строчки в программе ничего не менял!

Re[6]: Как правильно писать путь к файлу?

От: rg45
Дата: 03.03.06 13:39
Оценка: 4 (1)

Здравствуйте, AlexDav, Вы писали:

AD>Хотите верти — хотите нет, но
AD>

AD>#define DATA_FILE _T("C:\\Program Files\\Internet Explorer\\PLUGINS\\set.dln") AD>

AD>просто начала работать и все! Зуб даю кроме этой строчки в программе ничего не менял!

Впервоначальном варианте у тебя все слэши были двойные. А петерь вместо них одинарные бэк-слэши (литерал «\\» автоматически преобразуется в одинарный бэк-слэш). Значит, какая то из функций не могла вынести присутствия лишних символов в строке.


Не можешь достичь желаемого — пожелай достигнутого.
Re[6]: Как правильно писать путь к файлу?

От: i-maverick
Дата: 03.03.06 13:48
Оценка:

Здравствуйте, AlexDav, Вы писали:

AD>Хотите верти — хотите нет, но
AD>

AD>#define DATA_FILE _T("C:\\Program Files\\Internet Explorer\\PLUGINS\\set.dln") AD>

AD>просто начала работать и все! Зуб даю кроме этой строчки в программе ничего не менял!

Тебе ведь так и сказали — нужно либо одинарный прямой слэш, либо двойной обратный.
Ты бы хоть разобрался, зачем тут двойной слэш, чтоб больше не путаться.

Re[7]: Как правильно писать путь к файлу?

От: AlexDav
Дата: 03.03.06 13:54
Оценка:

Здравствуйте, i-maverick, Вы писали:

IM>Тебе ведь так и сказали — нужно либо одинарный прямой слэш, либо двойной обратный.
IM>Ты бы хоть разобрался, зачем тут двойной слэш, чтоб больше не путаться.

Ну ладно ругать то сразу — никто же не сказал что надо весь проект перекомпилить что бы подхватил эту дефайну

Спасибо — за время потраченное на меня

C++ как получить путь запущенного приложения?

использую c++17 c++20
имеется приложение, которое использует ресурсы используя относительные пути — как выяснить реальный путь в файловой системе до самого бинаря внутри кода?

апд
в общем найдено несколько способов:
1. только для систем с procfs — C++ как получить путь запущенного приложения? (комментарий)
2. по идее кроссплатформенный через sdl2 — C++ как получить путь запущенного приложения? (комментарий)
3. использовать метод нахождения используемый в which (определять является ли argv путем, если да то каким — относительным или абсолютным, если нет, то искать название бинарника по путям в env var PATH)

safocl ★★
15.01.21 01:50:13 MSK
1 2 3 →

я так понимаю std::filesystem не содержит такой возможности?

надо будет по подобию which делать ?

safocl ★★
( 15.01.21 02:24:46 MSK ) автор топика

Относительные относительно бинаря или таки рабочего каталога?

readlink(«/proc/self/exe», buf, bufsize)

anonymous
( 15.01.21 02:24:53 MSK )
Ответ на: комментарий от anonymous 15.01.21 02:24:53 MSK

относительные именно бинаря. — я просто юзаю файлы ресурсов — скажем бинарь может быть в /usr/bin, а ресы в /usr/share — неплоха было бы просто сделать ../share

но файл может же запускаться и просто по имени — тогда такой фокус не проходит по arcv[0].

safocl ★★
( 15.01.21 02:32:54 MSK ) автор топика
Ответ на: комментарий от anonymous 15.01.21 02:24:53 MSK

но походу да — для линукса тут будет именно readlink.
попробую в коде отвечу то или нет.

safocl ★★
( 15.01.21 02:38:53 MSK ) автор топика
Ответ на: комментарий от safocl 15.01.21 02:32:54 MSK

Если ты пишешь опенсорс и собрался складывать своё файло в /usr/bin и /usr/share, то эти пути, afaik, принято конфигурировать перед компиляцией. https://stackoverflow.com/questions/3239343/make-install-but-not-to-default-directories

anonymous
( 15.01.21 02:46:33 MSK )
Ответ на: комментарий от safocl 15.01.21 02:38:53 MSK

Это linux-специфично и непереносимо. Правильно сказали — конфигурировать пути при cборке.

slovazap ★★★★★
( 15.01.21 03:03:04 MSK )
Ответ на: комментарий от slovazap 15.01.21 03:03:04 MSK

https://en.cppreference.com/w/cpp/filesystem/read_symlink — я попробую вот енту функцию юзать — она вроде как тот сишный от unistd.h насколько я понимаю работает?

safocl ★★
( 15.01.21 03:04:57 MSK ) автор топика
Ответ на: комментарий от safocl 15.01.21 03:04:57 MSK

fs::read_symlink("/proc/self/exe")

работает именно так как я хотел

думаю можно закрывать.

для винды аналог как я понимаю енто GetModuleFileName?

safocl ★★
( 15.01.21 03:22:15 MSK ) автор топика
Ответ на: комментарий от safocl 15.01.21 03:04:57 MSK

Я не про readlink , а про /proc/self/exe — нигде кроме линукса её нет.

slovazap ★★★★★
( 15.01.21 03:35:01 MSK )
Ответ на: комментарий от slovazap 15.01.21 03:35:01 MSK

да понятно — ну в винде своя функция есть — через дефайны буду делать.

safocl ★★
( 15.01.21 03:50:42 MSK ) автор топика
Ответ на: комментарий от safocl 15.01.21 03:50:42 MSK

Кроме винды и линукса есть ещё куча операционных систем.

slovazap ★★★★★
( 15.01.21 04:14:35 MSK )
Ответ на: комментарий от slovazap 15.01.21 03:03:04 MSK

Правильно сказали — конфигурировать пути при cборке.

Это ещё хуже. Бинарник и данные должны работать из любого места.

X512 ★★★★★
( 15.01.21 04:24:49 MSK )
Ответ на: комментарий от slovazap 15.01.21 04:14:35 MSK

Кроме винды и линукса есть ещё куча операционных систем.

Ещё один #elif __OSNAME__ дописать. Можно ещё через argv[0] путь получить, но там могут быть символьные ссылки и относительные пути.

X512 ★★★★★
( 15.01.21 04:29:01 MSK )
Ответ на: комментарий от X512 15.01.21 04:29:01 MSK

в argv[0] еще может быть ваще другое — енто же не путь запускного файла — енто команда запуска — она может состоять из вообще других слов, нежели путь к exe.

в ентом то и проблема — пока я не начал устанавливать прогу в /usr/bin все было норм — но когда поставил туда и запустил не путем а командой — тоесть просто по названию проги — перестали действовать относительные пути к ресурсам.

я просто изначально думал чо в std::filesystem реализован механизм обнаружения пути к exe — но увы — нет.

safocl ★★
( 15.01.21 05:04:06 MSK ) автор топика
Последнее исправление: safocl 15.01.21 05:07:13 MSK (всего исправлений: 2)

Ответ на: комментарий от X512 15.01.21 04:24:49 MSK

потому что данные программа должна собирать с приоритетами:

  1. переменная среды MY_PROG_DATA
  2. через сборку препроцессора, $MY_PROG_DATA
  3. глобальное хостовые пути xdg
  4. пользовательские пути xdg

anonymous
( 15.01.21 06:06:07 MSK )
Ответ на: комментарий от anonymous 15.01.21 06:06:07 MSK

3 и 4 местами поменяй.

Siborgium ★★★★★
( 15.01.21 09:54:21 MSK )

Хрена вы норкоманы.

int main(int argc, char* argv[])

pon4ik ★★★★★
( 15.01.21 11:41:13 MSK )
Ответ на: комментарий от anonymous 15.01.21 06:06:07 MSK

Но в целом, глобальную проблему ТС решает именно такой подход, только и правда последние два пункта надо свапнуть.

pon4ik ★★★★★
( 15.01.21 11:48:57 MSK )

Резолвить argv[0] до абсолютного пути не помогает, если программа не была запущена по абсолютному пути:

$ cat ~/vcs/scripts/argv0.c #include int main(int argc, char ** argv) < puts(argv[0]); return 0; >$ make ~/vcs/scripts/argv0 cc argv0.c -o argv0 $ which argv0 /home/me/vcs/scripts/argv0 $ argv0 argv0 

(Не говоря уже о том, что в системном вызове execve в argv[0] можно подставить любую чушь, не имеющую ничего общего с путём к исполняемому файлу.)

anonymous
( 15.01.21 11:52:27 MSK )
Ответ на: комментарий от anonymous 15.01.21 11:52:27 MSK

Лол, значит я был не прав, интересный факт, спасибки.

pon4ik ★★★★★
( 15.01.21 11:54:41 MSK )
Ответ на: комментарий от pon4ik 15.01.21 11:41:13 MSK

Надо ещё символьные ссылки резолвить.

X512 ★★★★★
( 15.01.21 11:55:57 MSK )
Ответ на: комментарий от safocl 15.01.21 02:32:54 MSK

а ресы в /usr/share — неплоха было бы просто сделать ../share

Так делать глупо.

После старта бинарники:

  1. Он считывает переменные окружения PATH_БЛАБЛА_ДЛЯ_БЛА и т.п. Если их нет, то использует дефолт (man hier).
  2. Использует параметры, если их нет, то использует дефолты (man hier).
  3. Он читает конфиг, где определены пути. Если его нет, то использует дефолт (man hier).
  4. Он использует стандартные пути (man hier).

Полные пути рулят.

anonymous
( 15.01.21 12:16:07 MSK )
Ответ на: комментарий от safocl 15.01.21 05:04:06 MSK

Файловая система и твой ехе это как бы разные вещи, с чего бы рантайм лабуде быть в std::filesystem?

seiken ★★★★★
( 15.01.21 12:52:58 MSK )
Ответ на: комментарий от anonymous 15.01.21 06:06:07 MSK
safocl ★★
( 15.01.21 13:33:25 MSK ) автор топика
Ответ на: комментарий от pon4ik 15.01.21 11:41:13 MSK

чуть выше уже был коммент на счет argv[0] — енто не путь исполняемого файла — а команда запуска программы — она может быть ваще не путем, да и ваще не особо относиться к названию бинаря проги.

safocl ★★
( 15.01.21 13:35:42 MSK ) автор топика
Ответ на: комментарий от anonymous 15.01.21 12:16:07 MSK

ну в таком случае если ты портабельно собрал прогу она не найдет ресы.

safocl ★★
( 15.01.21 13:37:22 MSK ) автор топика
Ответ на: комментарий от seiken 15.01.21 12:52:58 MSK

путь там указывается.
да и текущий каталог ведь можно узнать через std::filesystem — енто тоже рантайм сущность.

safocl ★★
( 15.01.21 13:38:51 MSK ) автор топика

кстати нашел один кроссплатформенный способ — через SDL2/SDL_filesystem.h — функция SDL_GetBasePath() возвращает реальный путь нахождения проги.

safocl ★★
( 15.01.21 13:40:46 MSK ) автор топика
Последнее исправление: safocl 15.01.21 13:47:26 MSK (всего исправлений: 1)

Ответ на: комментарий от anonymous 15.01.21 02:24:53 MSK

argv[0] ёпта, при старте приложения.

deep-purple ★★★★★
( 15.01.21 13:41:20 MSK )
Ответ на: комментарий от safocl 15.01.21 13:37:22 MSK

Разговор же идёт про обычный вариант сборки (/usr/bin, /usr/share и т.п.). С портабельной версией придётся работать через переменные окружения или ./бла-бла. Тут даже спорить не нужно.

anonymous
( 15.01.21 13:49:05 MSK )
Ответ на: комментарий от slovazap 15.01.21 03:03:04 MSK

Это linux-специфично и непереносимо.

Можно натравить which или своровать код поиска (по списку путей в PATH).

anonymous
( 15.01.21 13:50:03 MSK )
Ответ на: комментарий от anonymous 15.01.21 13:50:03 MSK

да зачем если есть /proc/self/exe симлинк ведущий к бинарю?

safocl ★★
( 15.01.21 13:53:02 MSK ) автор топика
Ответ на: комментарий от safocl 15.01.21 13:53:02 MSK

Это linux-специфично и непереносимо.

Это если надо переносимо. Решение, естественно, неточное — нужно чтобы совпали алгоритмы и данные для поиска пути у приложения и у системы.

anonymous
( 15.01.21 13:59:37 MSK )
Ответ на: комментарий от X512 15.01.21 04:24:49 MSK

Это ещё хуже. Бинарник и данные должны работать из любого места.

  • Кто это сказал?
  • Какие аргументы?
  • В каких пределах это должно работать?

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

Претензия здесь не к одному из этих вариантов, потому что требование ровно одно — бинарник должен работать так как его установили, и ему удовлетворяют оба. Но к способу получения пути к бинарнику который непереносим, и быдлокод с /proc/self/exe просто сломается на *bsd, haiku, macos и ещё куче систем.

slovazap ★★★★★
( 15.01.21 14:53:10 MSK )
Ответ на: комментарий от slovazap 15.01.21 14:53:10 MSK

Но к способу получения пути к бинарнику который непереносим, и быдлокод с /proc/self/exe просто сломается на *bsd, haiku, macos и ещё куче систем.

ессесна — надо делать разные пути для проверки — сам способ не меняется на юникс подобных системах. — но выше же и сказано чо енто непереносимо.

safocl ★★
( 15.01.21 14:55:53 MSK ) автор топика
Ответ на: комментарий от X512 15.01.21 04:29:01 MSK

Ещё один #elif OSNAME дописать.

Это говённый код который надо допиливать под каждую новую систему чтобы запустить. Едва ли от автора можно ожидать что он знает как получить путь к бинарнику на всех существующих системах. И потом всё уткнётся в систему где этого сделать вообще нельзя и всё равно будет добавлен универсальный способ с абсолютным путём.

В итоге получаем:

  • Коллекцию способов получить путь к бинарнику на несколько страниц мёртвого кода, из которого тестируется только тот что работает на системе автора
  • Теряем поддержку относительной переносимости, потому что она уже не везде работает

Поэтому собственно везде и всегда используются абсолютные пути, и это единственный правильный способ.

Можно ещё через argv[0] путь получить, но там могут быть символьные ссылки и относительные пути.

Нельзя, если бинарник запущен через $PATH там вообще пути не будет. Поведение зависит от шелла и на самом деле там вообще не обязано оказаться что-либо осмысленное.

slovazap ★★★★★
( 15.01.21 15:08:17 MSK )
Ответ на: комментарий от slovazap 15.01.21 15:08:17 MSK

так а способ с применением sdl2 который я выше привел он что не везде работает где есть sdl2?

safocl ★★
( 15.01.21 15:10:12 MSK ) автор топика
Ответ на: комментарий от safocl 15.01.21 14:55:53 MSK

Какие ещё разные пути? На других системах нет никаких путей аналогичных /proc/self/exe

Как получить путь к файлу c

Доброго времени суток! Думаю где-то уже отвечали на такое но гугиль найти такое не помог. Нужно получить полный путь к файлу, переданный в качестве параметра командной строки, и использовать его для открытия файла и дальнейших манипуляций.
Вот мой кодец:

#include "stdafx.h" #include #include #include #include #include #include #include #include int _tmain(int argc, _TCHAR* argv[]) < setlocale(LC_ALL,"RUS"); SetConsoleCP(1251); SetConsoleOutputCP(1251); char *s,*s1,sc[7]; s=(char*)argv[1]; int i=0; CharToOem(argv[1],s1); while(s1[i]!=0)< printf("%c %i\n",s1[i],s1[i]); i++; >FILE *f=fopen(s1,"r"); if(f!=NULL) < fscanf(f,"s",sc); printf("%s",sc); >else < printf("NO"); >//[/преобразуем используя CharToOem] _getch(); for(int t=1;t printf("\n"); i+=2; > //[/вручную просматриваем _tchar: там четные поля-символы, нечетные, видимо, номера кодовых страниц] _getch(); return 0; >

т.е. нужно в любом случае изменять код русских символов, чтобы fopen могла их воспринимать.

ps вторую часть вывел сам; странно что CharToOem сразу не делает все хорошо;

вопщем вопрос такой: как? что? почему? можно сделать все хорошо и красиво

psps наличие или отсутствие следующих строчек на функционирование не повлияло
setlocale(LC_ALL,»RUS»);
SetConsoleCP(1251);
SetConsoleOutputCP(1251);

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *