How to get file extension from a string in C ++

Given the string "filename.conf" , how to check part of the extension?

I need a cross-platform solution.

+73
c ++ string filenames file-extension
Sep 09 '08 at 13:57
source share
24 answers

You must make sure that you care about file names with more than one dot. example: c:\.directoryname\file.name.with.too.many.dots.ext will not be processed correctly using strchr or find.

My favorite would be to increase the file system library , which has an extension function (paths)

+34
Sep 09 '08 at 14:27
source share

Is this too easy a solution?

 #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; } } 
+141
Sep 09 '08 at 14:23
source share

The best way is not to write any code that does this, but to call existing methods. In windows method

+42
Sep 09 '08 at 14:20
source share

Assuming you have access to the 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 } 

Edit: This is a cross-platform solution since you did not mention the platform. If you specifically use Windows, you will need to use the special Windows features mentioned by others in the stream.

+29
Sep 09 '08 at 14:20
source share

Someone else mentioned boost, but I just wanted to add the actual code for this:

 #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 
+23
09 Oct
source share

in fact, STL can do this without a lot of code, I advise you to learn a little about STL, because it allows you to do some fancy things, anyway this is what I use.

 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 solution will always return the extension even on lines like "this.abcdesmp3" if it cannot find the extension it will return. "

+19
Dec 22 '10 at 3:30
source share

Actually the easiest way is

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

Remember: if '.' does not exist in the file name, ext will be NULL .

+7
Jul 30 '13 at 10:26
source share

With C ++ 17 and its std::filesystem::path::extension (the library is the successor to boost :: filesystem), you would make your expression more expressive than, for example, using 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: eg "myFile.cfg is an invalid type" } } 

See also std :: filesystem :: path :: stem , std :: filesystem :: path :: filename .

+6
Jun 15 '18 at 19:28
source share

I myself came across this question, although I already had a working code, which I realized that it will not work in some cases.

Although some people have already suggested using some external libraries, I prefer to write my own code for training.

Some answers used the method that I used first (searching for the last "."), But I remembered that in linux, hidden files / folders start with ".". Therefore, if the file is hidden and has no extension, the entire file name will be accepted for the extension. To avoid this, I wrote this piece of code:

 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; } 

I have not tested this completely, but I think it should work.

+4
Nov 17 '12 at 11:26
source share
 _splitpath, _wsplitpath, _splitpath_s, _wsplitpath_w 

I think this is only Windows (Platform SDK)?

+3
Sep 09 '08 at 14:03
source share

Using std :: string find / rfind solves this problem, but if you work a lot with paths, you should look at boost :: filesystem :: path, as this will make your code much cleaner than messing with raw string indexes / iterators.

I suggest upgrading, as it is a high-quality, well-tested (open source and commercially) free and fully portable library.

+3
Dec 13 '09 at 21:34
source share

For char array strings you can use this:

 #include <ctype.h> #include <string.h> int main() { char filename[] = "apples.bmp"; char extension[] = ".jpeg"; if(compare_extension(filename, extension) == true) { // ..... } else { // ..... } return 0; } bool compare_extension(char *filename, char *extension) { /* Sanity checks */ if(filename == NULL || extension == NULL) return false; if(strlen(filename) == 0 || strlen(extension) == 0) return false; if(strchr(filename, '.') == NULL || strchr(extension, '.') == NULL) return false; /* Iterate backwards through respective strings and compare each char one at a time */ for(int i = 0; i < strlen(filename); i++) { if(tolower(filename[strlen(filename) - i - 1]) == tolower(extension[strlen(extension) - i - 1])) { if(i == strlen(extension) - 1) return true; } else break; } return false; } 

Can handle file paths in addition to file names. Works with both C and C ++. And cross platform.

+3
Jan 23 2018-11-23T00:
source share

NET / CLI version using System :: String

  System::String^ GetFileExtension(System::String^ FileName) { int Ext=FileName->LastIndexOf('.'); if( Ext != -1 ) return FileName->Substring(Ext+1); return ""; } 
+3
Jul 25 '11 at 20:05
source share

Good answers, but I see that most of them have some problems: First of all, I think a good answer should work for full file names that have their own route headers, it should also work for Linux or windows or, like already mentioned should be cross-platform. For most answers; file names without extension, but the path with the name of the folder, including the period, the function will not be able to return the correct extension: examples of some test cases may be as follows:

  const char filename1 = {"C:\\init.d\\doc"}; // => No extention const char filename2 = {"..\\doc"}; //relative path name => No extention const char filename3 = {""}; //emputy file name => No extention const char filename4 = {"testing"}; //only single name => No extention const char filename5 = {"tested/k.doc"}; // normal file name => doc const char filename6 = {".."}; // parent folder => No extention const char filename7 = {"/"}; // linux root => No extention const char filename8 = {"/bin/test.d.config/lx.wize.str"}; // ordinary path! => str 

The "brian newman" clause will not be executed for filename1 and filename4. and most other reverse search based answers fail for file name1. I suggest including the following method in your source: which is the function returning the index of the first character of the extension or the length of the specified string if not found.

 size_t find_ext_idx(const char* fileName) { size_t len = strlen(fileName); size_t idx = len-1; for(size_t i = 0; *(fileName+i); i++) { if (*(fileName+i) == '.') { idx = i; } else if (*(fileName + i) == '/' || *(fileName + i) == '\\') { idx = len - 1; } } return idx+1; } 

you can use the above code in your c ++ application as below:

 std::string get_file_ext(const char* fileName) { return std::string(fileName).substr(find_ext_idx(fileName)); } 

The last time in some cases a folder is given a file name as an argument and includes a period in the folder name, the function returns the layout point of the folder, therefore it is better for the user to first verify that this name is the file name, not the folder name.

+3
Nov 08 '14 at 22:49
source share

I would go with boost::filesystem::extension ( std::filesystem::path::extension with C ++ 17), but if you cannot use Boost and you just need to check the extension, a simple solution:

 bool ends_with(const std::string &filename, const std::string &ext) { return ext.length() <= filename.length() && std::equal(ext.rbegin(), ext.rend(), filename.rbegin()); } if (ends_with(filename, ".conf")) { /* ... */ } 
+3
May 2 '15 at 17:14
source share

I use these two functions to get the extension and file name without the extension:

 std::string fileExtension(std::string file){ std::size_t found = file.find_last_of("."); return file.substr(found+1); } std::string fileNameWithoutExtension(std::string file){ std::size_t found = file.find_last_of("."); return file.substr(0,found); } 

And these regex approaches are suitable for certain additional requirements:

 std::string fileExtension(std::string file){ std::regex re(".*[^\\.]+\\.([^\\.]+$)"); std::smatch result; if(std::regex_match(file,result,re))return result[1]; else return ""; } std::string fileNameWithoutExtension(std::string file){ std::regex re("(.*[^\\.]+)\\.[^\\.]+$"); std::smatch result; if(std::regex_match(file,result,re))return result[1]; else return file; } 

Additional requirements that are satisfied using the regex method:

  • If the file name is similar to .config or something like this, the extension will be an empty string, and the file name without the extension will be .config .
  • If the file name has no extension, the extension will be an empty string, the file name without the extension will remain unchanged.



EDIT:

Additional requirements can also be met as follows:

 std::string fileExtension(const std::string& file){ std::string::size_type pos=file.find_last_of('.'); if(pos!=std::string::npos&&pos!=0)return file.substr(pos+1); else return ""; } std::string fileNameWithoutExtension(const std::string& file){ std::string::size_type pos=file.find_last_of('.'); if(pos!=std::string::npos&&pos!=0)return file.substr(0,pos); else return file; } 

Note:

Pass only the file names (not the path) in the above functions.

+2
Aug 19 '15 at 20:03
source share

Try using strstr

 char* lastSlash; lastSlash = strstr(filename, "."); 
+1
May 11 '12 at 7:56 a.m.
source share

Or you can use this:

  char *ExtractFileExt(char *FileName) { std::string s = FileName; int Len = s.length(); while(TRUE) { if(FileName[Len] != '.') Len--; else { char *Ext = new char[s.length()-Len+1]; for(int a=0; a<s.length()-Len; a++) Ext[a] = FileName[s.length()-(s.length()-Len)+a]; Ext[s.length()-Len] = '\0'; return Ext; } } } 

This code is cross-platform

+1
Aug 7 '13 at 10:13 on
source share

If you use the Qt library, you can try the QFileInfo suffix ()

+1
Mar 02 '14 at 11:03
source share

Here is a function that takes the path / file name as a string and returns the extension as a string. All this is standard C ++, and a cross-platform platform should work for most platforms.

Unlike a few other answers here, it handles odd cases handled by PathFindExtension windows based on the PathFindExtensions documentation.

 wstring get_file_extension( wstring filename ) { size_t last_dot_offset = filename.rfind(L'.'); // This assumes your directory separators are either \ or / size_t last_dirsep_offset = max( filename.rfind(L'\\'), filename.rfind(L'/') ); // no dot = no extension if( last_dot_offset == wstring::npos ) return L""; // directory separator after last dot = extension of directory, not file. // for example, given C:\temp.old\file_that_has_no_extension we should return "" not "old" if( (last_dirsep_offset != wstring::npos) && (last_dirsep_offset > last_dot_offset) ) return L""; return filename.substr( last_dot_offset + 1 ); } 
+1
Apr 28 '14 at 16:51
source share

This is the solution I came across. Then I noticed that it looks like what @serengeor posted.

It works with std::string and find_last_of , but the main idea will also work if the use of char and strrchr arrays is changed. It processes hidden files and additional points representing the current directory. It is platform independent.

 string PathGetExtension( string const & path ) { string ext; // Find the last dot, if any. size_t dotIdx = path.find_last_of( "." ); if ( dotIdx != string::npos ) { // Find the last directory separator, if any. size_t dirSepIdx = path.find_last_of( "/\\" ); // If the dot is at the beginning of the file name, do not treat it as a file extension. // eg, a hidden file: ".alpha". // This test also incidentally avoids a dot that is really a current directory indicator. // eg: "alpha/./bravo" if ( dotIdx > dirSepIdx + 1 ) { ext = path.substr( dotIdx ); } } return ext; } 

Unit test:

 int TestPathGetExtension( void ) { int errCount = 0; string tests[][2] = { { "/alpha/bravo.txt", ".txt" }, { "/alpha/.bravo", "" }, { ".alpha", "" }, { "./alpha.txt", ".txt" }, { "alpha/./bravo", "" }, { "alpha/./bravo.txt", ".txt" }, { "./alpha", "" }, { "c:\\alpha\\bravo.net\\charlie.txt", ".txt" }, }; int n = sizeof( tests ) / sizeof( tests[0] ); for ( int i = 0; i < n; ++i ) { string ext = PathGetExtension( tests[i][0] ); if ( ext != tests[i][1] ) { ++errCount; } } return errCount; } 
+1
Aug 19 '15 at 21:20
source share

If you use Poco libraries you can do:

 #include <Poco/Path.h> ... std::string fileExt = Poco::Path("/home/user/myFile.abc").getExtension(); // == "abc" 
0
Nov 16 '15 at 6:46
source share

If you consider the extension as the last point and possible characters after it, but only if they do not contain a directory separator character, the next function returns the initial index of the extension, or -1 if the extension is not found. When you have this, you can do whatever you want, for example, stretch the extension, change it, check it, etc.

 long get_extension_index(string path, char dir_separator = '/') { // Look from the end for the first '.', // but give up if finding a dir separator char first for(long i = path.length() - 1; i >= 0; --i) { if(path[i] == '.') { return i; } if(path[i] == dir_separator) { return -1; } } return -1; } 
0
Dec 17 '15 at 10:59
source share

I used the PathFindExtension () function to find out if this is a valid tif file or not.

 #include <Shlwapi.h> bool A2iAWrapperUtility::isValidImageFile(string imageFile) { char * pStrExtension = ::PathFindExtension(imageFile.c_str()); if (pStrExtension != NULL && strcmp(pStrExtension, ".tif") == 0) { return true; } return false; } 
0
Jan 20 '16 at 17:24
source share



All Articles