Как получить расширение файла из строки в C ++ - PullRequest
73 голосов
/ 09 сентября 2008

Учитывая строку "filename.conf", как проверить часть расширения?

Мне нужно кроссплатформенное решение.

Ответы [ 24 ]

137 голосов
/ 09 сентября 2008

Это слишком простое решение?

#include <iostream>
#include <string>

int main()
{
  std::string fn = "filename.conf";
  if(fn.substr(fn.find_last_of(".") + 1) == "conf") {
    std::cout << "Yes..." << std::endl;
  } else {
    std::cout << "No..." << std::endl;
  }
}
43 голосов
/ 09 сентября 2008

Лучший способ - не писать код, который делает это, а вызывать существующие методы. В Windows метод PathFindExtension , вероятно, самый простой.

Так почему бы вам не написать свой собственный?

Хорошо, возьмите пример strrchr, что происходит, когда вы используете этот метод в следующей строке "c: \ program files \ AppleGate.Net \ readme"? Является ли расширение .Net \ readme расширением? Легко написать что-то, что работает для нескольких примеров, но гораздо труднее написать что-то, что работает для всех случаев.

34 голосов
/ 09 сентября 2008

Вы должны убедиться, что позаботились об именах файлов с более чем одной точкой. пример: c:\.directoryname\file.name.with.too.many.dots.ext не будет правильно обрабатываться strchr или find.

Моим любимым вариантом будет библиотека файловой системы boost с функцией расширения (path)

30 голосов
/ 09 сентября 2008

Если у вас есть доступ к STL:

std::string filename("filename.conf");
std::string::size_type idx;

idx = filename.rfind('.');

if(idx != std::string::npos)
{
    std::string extension = filename.substr(idx+1);
}
else
{
    // No extension found
}

Редактировать: Это кроссплатформенное решение, так как вы не упомянули платформу. Если вы используете Windows, вам нужно использовать специальные функции Windows, упомянутые другими в этой теме.

23 голосов
/ 09 октября 2012

Кто-то еще упомянул надстройку, но я просто хотел добавить реальный код, чтобы сделать это:

#include <boost/filesystem.hpp>
using std::string;
string texture         = foo->GetTextureFilename();
string file_extension  = boost::filesystem::extension(texture);
cout << "attempting load texture named " << texture
     << "    whose extensions seems to be " 
     << file_extension << endl;
// Use JPEG or PNG loader function, or report invalid extension
17 голосов
/ 22 декабря 2010

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

std::string GetFileExtension(const std::string& FileName)
{
    if(FileName.find_last_of(".") != std::string::npos)
        return FileName.substr(FileName.find_last_of(".")+1);
    return "";
}

это решение всегда будет возвращать расширение даже для строк типа "this.a.b.c.d.e.s.mp3", если не может найти расширение, оно вернет "".

8 голосов
/ 30 июля 2013

На самом деле самый простой способ -

char* ext;
ext = strrchr(filename,'.') 

Одна вещь, которую следует запомнить: если '.' не существует в имени файла, ext будет NULL.

5 голосов
/ 17 ноября 2012

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

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

Некоторые ответы включали метод, который я использовал в первую очередь (в поисках последнего "."), Но я вспомнил, что в linux скрытые файлы / папки начинаются с ".". Таким образом, если файл скрыт и не имеет расширения, все имя файла будет взято за расширение. Чтобы избежать этого, я написал этот кусок кода:

bool getFileExtension(const char * dir_separator, const std::string & file, std::string & ext)
{
    std::size_t ext_pos = file.rfind(".");
    std::size_t dir_pos = file.rfind(dir_separator);

    if(ext_pos>dir_pos+1)
    {
        ext.append(file.begin()+ext_pos,file.end());
        return true;
    }

    return false;
}

Я не проверил это полностью, но думаю, что оно должно работать.

4 голосов
/ 15 июня 2018

С C ++ 17 и его std::filesystem::path::extension (библиотека является преемником boost :: filesystem), вы сделаете ваше утверждение более выразительным, чем, например, с помощью, например. std::string.

#include <iostream>
#include <filesystem> // C++17
namespace fs = std::filesystem;

int main()
{
    fs::path filePath = "my/path/to/myFile.conf";
    if (filePath.extension() == ".conf") // Heed the dot.
    {
        std::cout << filePath.stem() << " is a valid type."; // Output: "myFile is a valid type."
    }
    else
    {
        std::cout << filePath.filename() << " is an invalid type."; // Output: e.g. "myFile.cfg is an invalid type"
    }
}

См. Также std :: filesystem :: path :: stem , std :: filesystem :: path :: filename .

4 голосов
/ 09 сентября 2008
_splitpath, _wsplitpath, _splitpath_s, _wsplitpath_w

Я думаю, что это только Windows (Platform SDK)?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...