8 ответов:
чтобы извлечь имя файла без расширения, используйте boost::filesystem:: path:: stem вместо уродливого std:: string:: find_last_of(".")
boost::filesystem::path p("c:/dir/dir/file.ext"); std::cout << "filename and extension : " << p.filename() << std::endl; // file.ext std::cout << "filename only : " << p.stem() << std::endl; // file
если вы хотите безопасный способ (т. е. переносимый между платформами и не поставив предположений по пути), я бы рекомендовал использовать
boost::filesystem.это выглядело бы как-то так:
boost::filesystem::path my_path( filename );затем вы можете извлечь различные данные из этого пути. вот документация объекта path.
кстати: также помните, что для того, чтобы использовать путь, как
c:\foto\foto2003\shadow.gifвам нужно бежать
\в строке дословно:const char* filename = "c:\foto\foto2003\shadow.gif";или использовать
/вместо:const char* filename = "c:/foto/foto2003/shadow.gif";это относится только к указанию литеральных строк в
""кавычки, проблема не существует, когда вы загружаете пути из файла.
вы должны будете прочитать ваши имена файлов из файла в
std::string. Вы можете использовать оператор извлечения строкиstd::ostream. После того, как у вас есть имя файла вstd::stringможно использоватьstd::string::find_last_ofметод поиска последнего разделителя.что-то вроде этого:
std::ifstream input("file.log"); while (input) { std::string path; input >> path; size_t sep = path.find_last_of("\/"); if (sep != std::string::npos) path = path.substr(sep + 1, path.size() - sep - 1); size_t dot = path.find_last_of("."); if (dot != std::string::npos) { std::string name = path.substr(0, dot); std::string ext = path.substr(dot, path.size() - dot); } else { std::string name = path; std::string ext = ""; } }
на C++17:
#include <filesystem> std::filesystem::path p("c:/dir/dir/file.ext"); std::cout << "filename and extension: " << p.filename() << std::endl; // "file.ext" std::cout << "filename only: " << p.stem() << std::endl; // "file"ссылка на файловую систему:http://en.cppreference.com/w/cpp/filesystem
как было предложено @RoiDanto для форматирования выходных данных
std::outможет окружать вывод котировками, например:filename and extension: "file.ext"вы можете конвертировать
std::filesystem::pathдоstd::stringbyp.filename().string()если это то, что вам нужно, например:filename and extension: file.ext
не код, но вот такая идея:
- читать
std::stringиз входного потока (std::ifstream), каждый экземпляр будет полный путь- сделать
find_last_ofна строку\- извлеките подстроку из этой позиции до конца, теперь это даст вам имя файла
- сделать
find_last_ofна., и подстрока с обеих сторон даст вам имя + расширение.
Я также использую этот фрагмент для определения соответствующего символа косой черты:
boost::filesystem::path slash("/"); boost::filesystem::path::string_type preferredSlash = slash.make_preferred().native();а затем замените косую черту на предпочтительную косую черту для ОС. Полезно, если он постоянно развертывается между Linux/Windows.
для linux или unix машин, ОС имеет две функции, связанные с пути и имена файлов. используйте man 3 basename, чтобы получить дополнительную информацию об этих функциях. Преимущество использования системной функциональности заключается в том, что вам не нужно устанавливать boost или писать свои собственные функции.
#include <libgen.h> char *dirname(char *path); char *basename(char *path);пример кода из man-страницы:
char *dirc, *basec, *bname, *dname; char *path = "/etc/passwd"; dirc = strdup(path); basec = strdup(path); dname = dirname(dirc); bname = basename(basec); printf("dirname=%s, basename=%s\n", dname, bname);из-за неконстантного типа аргумента функции basename() это немного не прямолинейно используя это внутри кода C++. Вот простой пример из моей базы кода:
string getFileStem(const string& filePath) const { char* buff = new char[filePath.size()+1]; strcpy(buff, filePath.c_str()); string tmp = string(basename(buff)); string::size_type i = tmp.rfind('.'); if (i != string::npos) { tmp = tmp.substr(0,i); } delete[] buff; return tmp; }использование new / delete не является хорошим стилем. Я мог бы положить его в try / catch блок на случай, если что-то произошло между двумя вызовами.
ответы Николая Меркина и Ючен Чжуна велики, но, однако, из комментариев Вы можете видеть, что это не совсем точно.
неявное преобразование в std:: string при печати обернет имя файла в кавычки. Комментарии также не точны.
path::filename()иpath::stem()возвращает новый объект path иpath::string()возвращает ссылку на строку. Таким образом что-то вродеstd::cout << file_path.filename().string() << "\n"может вызвать проблемы с висячей ссылкой, так как строка, которую опорные пункты могли быть уничтожены.
Comments