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

Обновлено: 07.07.2024

У меня есть список файлов, хранящихся в .log в этом синтаксисе:

Я хочу извлечь имя и расширение из этих файлов. Можете ли вы привести пример простого способа сделать это?

ОТВЕТЫ

Ответ 1

Чтобы извлечь имя файла без расширения, используйте boost:: filesystem:: path:: stem вместо уродливого std::string:: find_last_of ( "." )

Ответ 2

Если вам нужен безопасный способ (т.е. переносимый между платформами и не устанавливающий предположения на пути), я бы рекомендовал использовать boost::filesystem .

Это выглядело бы так:

Затем вы можете извлечь различные данные с этого пути. Здесь документация объекта пути.

Кстати: Также помните, что для использования пути, типа

вам нужно избежать \ в строковом литерале:

Или используйте / вместо этого:

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

Ответ 3

Вам нужно будет прочитать ваши имена файлов из файла в std::string . Вы можете использовать оператор извлечения строки std::ostream . Когда у вас есть имя файла в std::string , вы можете использовать метод std::string::find_last_of , чтобы найти последний разделитель.

Что-то вроде этого:

Ответ 4

Не код, но вот идея:

  • Прочитайте std::string из входного потока ( std::ifstream ), каждый прочитанный экземпляр будет полным путем
  • Сделайте find_last_of в строке для \
  • Извлеките подстроку из этой позиции до конца, теперь она даст вам имя файла
  • Сделайте find_last_of для . , а подстрока с обеих сторон даст вам имя + расширение.

Ответ 5

Для С++ 17:

Как было предложено @RoiDanto, для форматирования вывода std::out может окружать вывод с помощью котировок, например:

Вы можете преобразовать std::filesystem::path в std::string на p.filename().string() , если это вам нужно, например:

Ответ 6

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

а затем замените косые черты на предпочтительную косую черту для ОС. Полезно, если вы постоянно развертываете Linux/Windows.

Ответ 7

Для Linux или Unix-устройств os имеет две функции, связанные с именами путей и файлов. используйте man 3 basename, чтобы получить дополнительную информацию об этих функциях. Преимущество использования предоставляемой системой функциональности заключается в том, что вам не нужно устанавливать boost или писать собственные функции.

Пример кода с man-страницы:

Из-за типа аргумента non-const функции basename() это немного не прямолинейно, используя этот код внутри С++. Вот простой пример из моей базы кода:

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

у меня есть список файлов, хранящийся в .log в следующий синтаксис:

Я хочу извлечь имя и расширение из этих файлов. Можете ли вы привести пример простого способа сделать это?

чтобы извлечь имя файла без расширения, используйте boost::filesystem:: path:: stem вместо уродливого std:: string:: find_last_of(".")

если вы хотите безопасный способ (т. е. переносимый между платформами и не поставив предположений по пути), я бы рекомендовал использовать boost::filesystem .

это выглядело бы как-то так:

затем вы можете извлечь различные данные из этого пути. вот документация объекта path.

кстати: также помните, что для того, чтобы использовать путь, как

вам нужно бежать \ в строке дословно:

или использовать / вместо:

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

вы должны будете прочитать ваши имена файлов из файла в std::string . Вы можете использовать оператор извлечения строки std::ostream . После того, как у вас есть имя файла в std::string можно использовать std::string::find_last_of метод поиска последнего разделителя.

что-то вроде этого:

  1. читать std::string из входного потока ( std::ifstream ), каждый экземпляр будет полный путь
  2. сделать find_last_of на строку \
  3. извлеките подстроку из этой позиции до конца, теперь это даст вам имя файла
  4. сделать find_last_of на . , и подстрока с обеих сторон даст вам имя + расширение.

Я также использую этот фрагмент для определения соответствующего символа косой черты:

а затем замените косую черту на предпочтительную косую черту для ОС. Полезно, если он постоянно развертывается между Linux/Windows.

для linux или unix машин, ОС имеет две функции, связанные с пути и имена файлов. используйте man 3 basename, чтобы получить дополнительную информацию об этих функциях. Преимущество использования системной функциональности заключается в том, что вам не нужно устанавливать boost или писать свои собственные функции.

пример кода из man-страницы:

из-за неконстантного типа аргумента функции basename() это немного не прямолинейно используя это внутри кода C++. Вот простой пример из моей базы кода:

использование new / delete не является хорошим стилем. Я мог бы положить его в try / catch блок на случай, если что-то произошло между двумя вызовами.

У меня есть список файлов, хранящихся в .log с таким синтаксисом:

Я хочу извлечь имя и расширение из этих файлов. Вы можете привести простой способ сделать это?

Чтобы извлечь имя файла без расширения, используйте boost :: filesystem :: path :: stem вместо уродливого std :: string :: find_last_of (".")

Для C ++ 17 :

Как предлагает @RoiDanto , для форматирования вывода std::out может заключать вывод в кавычки, например:

Вы можете преобразовать std::filesystem::path в std::string с помощью p.filename().string() , если вам это нужно, например:

Если вам нужен безопасный способ (т.е. переносимость между платформами и отсутствие допущений в пути), я бы рекомендовал использовать boost::filesystem .

Это выглядело бы как-то так:

Затем вы можете извлекать различные данные из этого пути. Вот документация по объекту пути.

BTW: Также помните, что для использования пути вроде

Вам нужно экранировать \ в строковом литерале:

Или используйте вместо этого / :

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

Вам нужно будет прочитать свои имена файлов из файла в std::string . Вы можете использовать оператор извлечения строки std::ostream . Если у вас есть имя файла в std::string , вы можете использовать метод std::string::find_last_of , чтобы найти последний разделитель.

Что-то вроде этого:

  1. Прочтите std::string из входного потока ( std::ifstream ), каждый прочитанный экземпляр будет полным путем
  2. Сделайте find_last_of на строке для \
  3. Извлеките подстроку из этой позиции до конца, теперь это даст вам имя файла
  4. Сделайте find_last_of вместо . , и подстрока с любой стороны даст вам имя + расширение.

Попробуйте следующий трюк, чтобы извлечь имя файла из пути без расширения в C ++ и без внешних библиотек в C ++:

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

А затем замените косую черту предпочтительной косой чертой для ОС. Полезно, если вы постоянно выполняете развертывание между Linux / Windows.

Для машин linux или unix в ОС есть две функции, касающиеся пути и имен файлов. используйте man 3 basename, чтобы получить больше информации об этих функциях. Преимущество использования функций, предоставляемых системой, заключается в том, что вам не нужно устанавливать boost или писать свои собственные функции.

Пример кода со страницы руководства:

Из-за неконстантного типа аргумента функции basename () использование этого внутри кода C ++ немного непросто. Вот простой пример из моей кодовой базы:

Использование new / delete - не лучший стиль. Я мог бы поместить его в блок try / catch на случай, если что-то произойдет между двумя вызовами.

Ответы Николая Меркина и Ючена Чжуна великолепны, но, тем не менее, из комментариев вы можете видеть, что они не совсем точны.

Неявное преобразование в std :: string при печати приведет к заключению имени файла в кавычки. Комментарии тоже неточные.


Казалось бы — что может быть проще, чем работа с файлами в C++. Но отдельные личности поражают своей находчивостью в поиске наихудшего подхода.
Не стоит делать так:

std::string filepath("C:\\тест");
std::ofstream file(filepath.c_str());


Если кратко, то использование не ASCII символов в строковых константах char может привести к печальным последствиям. Я уже обсуждал этот вопрос в посте о кодировках. В данном случае название файла напрямую зависит от кодировки исходника и если кто-то напишет подобное в utf-8, в windows-xp можно получить файл с запрещенными символами, с которым невозможно будет ничего сделать. Можно не использовать не ASCII. Но вы же не можете запретить это пользователю (потоку или БД из которого получен путь). Это же дискриминация по национальному признаку! Срочно исправляемся:

std::wstring filepath= L"C:\тест"
std::ofstream file(filepath.c_str());

Несведущие в стандарте пользователи Visual Studio могут успокоиться, пока нужда не заставит сменить компилятор (точнее STL). И тут начинается…

— «дурацкий gcc» или «дурацкий stlport» не содержит конструктор ofstream::ofstream(wchar_t*)

Дело в том, что текущий стандарт и не предполагает его наличия (не трогаем пока C++0x). Это в чистом виде энтузиазм мелкомягких.

Что же делать?

  • Использовать стороннюю библиотеку для работы с путями (к примеру boost::filesystem)
  • Использовать std::locale
  • Придумывать свой

С третьим вариантом все ясно, с первым тоже ничего сложного:

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

Пользуемся std::locale

Отступление.
Огорчу пользователей mingw: вам придется использовать стороннюю реализацию STL (к примеру stlport) из-за отсутствия в родной правильной поддержки локализации. А точнее, функция std::locale("") всегда возвращает std::locale(«C»), что бы там у вас не стояло. Тот же stlport лишен подобного недостатка. О том как слепить связку mingw+stlport+boost я отписал тут.

Все что нам нужно сделать это следовать простым правилам — с не ASCII работаем в «расширенном» виде. То есть, читаем путь в std::wstring, используя соответствующим образом локализованный поток, а при использовании, сужаем по пользовательской локализации. Эта идея основана на том, что раз пользователь правильно видит символы своего языка в консоли, то его пользовательская локализация знает в какую кодировку надо сузить широкую строку, чтобы правильно интерпретировать путь. Итак, пример. Допустим у нас есть файл в кодировке cp866, содержащий путь. Нам необходимо создать файл по этому пути. Что мы делаем:

Фасеты можно взять на git-hub.

SUMMARY

Если вы используете путь из argv — можете смело с ним работать (пользователь знает что делает). Из «внешней среды» путь получайте с помощью правильно локализованного потока как широкую строку и сужайте ее с помощью пользовательской локализации.

С вопросами можно обращаться:
0. К стандарту
1. К книге Страуструпа (3-е специальное издание, приложение)
2. К документации по mingw.
3. К документации по boost.
4. К посту о фасетах и кодировках.

Всем прямых путей!

UPD: Ну и как правильно заметили Gorthauer87,Migun и naryl в комментариях, обратные слеши и платформо-специфичные пути тоже плохая идея.

Читайте также: