2012-04-23 7 views
2

Я пытаюсь открыть файл в большом коде.Открытие файла в C++, относительного или абсолютного?

Мне сказали, что при работе с файлами лучше использовать абсолютный путь, а не относительный путь. Однако этот код должен использоваться разными людьми, которые могут размещать источники в разных местах (/ home/username или/home/username/desktop /, например), поэтому я думаю, что было бы лучше использовать относительный путь к доступ к моему файлу конфигурации, потому что я знаю, где он относится к моему файлу cpp.

Вот короткая сумма складывается из местоположения файлов, имеющих отношение к моему вопросу:

  • файл Я хочу, чтобы прочитать это /home/me/myproject/config/myfile.txt

  • файл я читаю его от является /home/me/myproject/src/myfile.cpp

  • файл, который содержит «главный» также /home/me/myproject/src/myfile.cpp (это один файл огромен).

Я запускаю исполняемый файл из затмения. Я думаю, что eclipse устанавливает рабочий каталог в каталог, где «main» (/ home/me/myproject/src /).

Я озадачен тем фактом, что когда я собираюсь вызвать файл.open(), рабочий каталог (getcwd()) теперь есть/home/me/myproject /. По-видимому, рабочий каталог был изменен кодом между main() и моим вызовом file.open().

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

+1

Сообщите вашему приложению, где файл конфигурации находится в командной строке. – Nick

+0

Вам это нужно для работы на любой платформе или только в UNIX-подобных? – leftaroundabout

ответ

2

Я запускаю исполняемый файл из затмения. Я думаю, что eclipse устанавливает рабочий каталог в каталог, где «main» - (/ home/me/myproject/src /).

Уверены ли вы в этом? . Мне кажется, что это верхний уровень папки проекта (то есть, что-то вроде «/ дома/затмение/MyProject», а не «/ дома/затмение/ЦСИ» Это объясняет, почему:

рабочий каталог (getcwd()) Теперь есть/главная/мне/MyProject /.

было ли когда-нибудь что-нибудь еще? это очень маловероятно, что он был «изменен другой части программы», если явно не сделал что-то для этого.

Мне непонятно, что вы понимаете разницу между Исходный код и исполняемый файл. Файл исходного кода не запускается. Он скомпилирован в исполняемый файл, и это то, что выполняется. С eclipse они по умолчанию помещаются в Release/или Debug/(посмотрите), а не в каталог src /. Предполагаемая причина, по которой eclipse использует каталог toplevel, является согласованностью между этими версиями, и поэтому вы можете, например, выводить относительно этого.

Мой вопрос: он кажется очень подвержен ошибкам, чтобы полагаться на рабочий каталог,

Это, безусловно, верно независимо. Существуют специальные способы установки пути к домашнему каталогу пользователя. Вы должны это получить и указать в документации, где должна храниться конфигурация. Если пользователь не может сделать это правильно, это не ваша ошибка, но выдается информационное сообщение, например. «Файл конфигурации не найден!».

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

Обратите внимание, что «другие разработчики» не обязательно включать в себя источник вообще, так как не требуется, чтобы запустить исполняемый .

-1

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

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

Затем вы можете отключить имя файла и добавить имя файла конфигурации в путь (сохраненный в String base в следующем примере). Вот какой код, который определяет, является ли путь абсолютным или относительным, и добавляет его соответствующим образом. Вам нужно boost_filesystem для кроссплатформенности:

#ifdef WITH_BOOST_FILESYSTEM 
    boost::filesystem::path basepath(base), filepath(filename); 
    if (!basepath.is_complete()) { 
     basepath = filepath.remove_leaf() /= basepath; 
     base = basepath.string(); 
    } 
#elif __unix__ 
    if (base[0] != '/') { 
     char *f = strdup(filename.c_str()), *d = dirname(f); 
     base = string(d).append("/").append(base); 
     free(f); 
    } 
#else 
    std::cerr << "Warning: only absolute file paths accepted." << std::endl; 
#endif 
    base.append("/"); 
+0

Downvote для использования strdup на std :: string, не освобождая память, возвращенную strdup и отсутствующую декларацию базы. – SigTerm

+0

Это фрагмент кода, что вы можете угадать из текста. Но спасибо за ваши * добрые * отладочные усилия в любом случае. – ypnos

+0

Из справочной страницы dirname: «И dirname(), и basename() могут изменять содержимое пути, поэтому может быть желательно передать копию при вызове одной из этих функций». Вот почему strdup необходим. c_str() дает только указатель const. – ypnos

Смежные вопросы