Biorąc pod uwagę ciąg "filename.conf"
, jak zweryfikować część rozszerzenia?
Potrzebuję rozwiązania wieloplatformowego.
c++
string
filenames
file-extension
JeffV
źródło
źródło
Czy to zbyt proste rozwiązanie?
#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; } }
źródło
return "Yes...";
bez sprawdzenia - zakłada się, że rozwiązanie powinno działać dla innych danych wejściowych. Jako inny przeciwny przykład, plik o nazwie po prostu „conf” bez rozszerzenia również zwróciłby „Tak ...”, biorąc pod uwagę powyższe.boost::filesystem
, co jest trywialne w użyciu, ale zapewnia niezbędne wsparcie. Zobacz boost.org/doc/libs/1_55_0/libs/filesystem/doc/index.htmNajlepszym sposobem jest nie pisanie kodu, który to robi, ale wywołanie istniejących metod. W systemie Windows metoda PathFindExtension jest prawdopodobnie najprostsza.
Więc dlaczego nie miałbyś napisać własnego?
Cóż, weźmy przykład strrchr, co się stanie, gdy użyjesz tej metody w następującym ciągu „c: \ program files \ AppleGate.Net \ readme”? Czy „.Net \ readme” jest rozszerzeniem? Łatwo jest napisać coś, co działa w kilku przykładowych przypadkach, ale może być znacznie trudniej napisać coś, co działa we wszystkich przypadkach.
źródło
Zakładając, że masz dostęp do 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 }
Edycja: jest to rozwiązanie wieloplatformowe, ponieważ nie wspomniałeś o platformie. Jeśli korzystasz z systemu Windows, będziesz chciał wykorzystać specyficzne funkcje systemu Windows wspomniane przez innych w wątku.
źródło
Ktoś inny wspomniał o wzmocnieniu, ale chciałem tylko dodać rzeczywisty kod, aby to zrobić:
#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
źródło
w rzeczywistości STL może to zrobić bez dużej ilości kodu, radzę dowiedzieć się trochę o STL, ponieważ pozwala ci zrobić kilka wymyślnych rzeczy, w każdym razie tego używam.
std::string GetFileExtension(const std::string& FileName) { if(FileName.find_last_of(".") != std::string::npos) return FileName.substr(FileName.find_last_of(".")+1); return ""; }
to rozwiązanie zawsze zwróci rozszerzenie, nawet w przypadku łańcuchów typu „this.abcdesmp3”, jeśli nie może znaleźć rozszerzenia, zwróci „”.
źródło
Z C ++ 17 i jego
std::filesystem::path::extension
(biblioteka jest następcą boost :: filesystem) uczyniłbyś swoją instrukcję bardziej ekspresyjną niż użycie npstd::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" } }
Zobacz także std :: filesystem :: path :: stem , std :: filesystem :: path :: filename .
źródło
Właściwie najłatwiej jest
char* ext; ext = strrchr(filename,'.')
Jedna rzecz do zapamiętania: jeśli
'.'
nie istnieje w nazwie pliku, ext będzieNULL
.źródło
Sam natknąłem się dzisiaj na to pytanie, chociaż miałem już działający kod, zorientowałem się, że w niektórych przypadkach nie zadziała.
Podczas gdy niektórzy już sugerowali użycie zewnętrznych bibliotek, ja wolę pisać własny kod do celów edukacyjnych.
Niektóre odpowiedzi zawierały metodę, której użyłem w pierwszej kolejności (szukanie ostatniego „.”), Ale pamiętałem, że w Linuksie ukryte pliki / foldery zaczynają się od „.”. Więc jeśli plik jest ukryty i nie ma rozszerzenia, cała nazwa pliku zostanie wzięta za rozszerzenie. Aby tego uniknąć, napisałem ten fragment kodu:
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; }
Nie testowałem tego w pełni, ale myślę, że powinno działać.
źródło
Użycie funkcji find / rfind std :: string rozwiązuje TEN problem, ale jeśli dużo pracujesz ze ścieżkami, powinieneś spojrzeć na boost :: filesystem :: path, ponieważ sprawi, że twój kod będzie znacznie czystszy niż majstrowanie przy indeksach / iteratorach ciągów.
Sugeruję ulepszenie, ponieważ jest to wysokiej jakości, dobrze przetestowana (open source i komercyjnie) bezpłatna iw pełni przenośna biblioteka.
źródło
W przypadku łańcuchów znaków typu tablica możesz użyć tego:
#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; }
Obsługuje ścieżki plików oprócz nazw plików. Działa z C i C ++. I wieloplatformowy.
źródło
strlen(extension)
wfor
stanie. Następnie, jeśli znaki nie pasują, zwróć false.for
Pętla zewnętrzna zwraca prawdę.Dobre odpowiedzi, ale widzę, że większość z nich ma pewne problemy: Przede wszystkim uważam, że dobra odpowiedź powinna działać w przypadku pełnych nazw plików, które mają swoje nagłówki ścieżek, a także powinna działać dla systemu Linux lub Windows lub, jak wspomniano, powinna być wieloplatformowa. W przypadku większości odpowiedzi; nazwy plików bez rozszerzenia, ale ścieżka z nazwą folderu zawierającą kropkę, funkcja nie zwróci prawidłowego rozszerzenia: przykłady niektórych przypadków testowych mogą wyglądać następująco:
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
Sugestia „ brian newman ” nie powiedzie się dla nazwy pliku1 i nazwy pliku4. a większość innych odpowiedzi opartych na wyszukiwaniu wstecznym nie powiedzie się dla nazwy_pliku1. Proponuję uwzględnić w źródle następującą metodę: która jest funkcją zwracającą indeks pierwszego znaku rozszerzenia lub długość podanego ciągu, jeśli nie zostanie znaleziony.
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; }
możesz użyć powyższego kodu w swojej aplikacji c ++, jak poniżej:
std::string get_file_ext(const char* fileName) { return std::string(fileName).substr(find_ext_idx(fileName)); }
W ostatnim punkcie w niektórych przypadkach folder a jest podawany jako argument jako nazwa pliku i zawiera kropkę w nazwie folderu, funkcja zwróci kropkę folderu na końcu, aby użytkownik najpierw sprawdził, czy podana nazwa jest nazwą pliku, a nie nazwą folderu.
źródło
Wersja NET / CLI używająca System :: String
System::String^ GetFileExtension(System::String^ FileName) { int Ext=FileName->LastIndexOf('.'); if( Ext != -1 ) return FileName->Substring(Ext+1); return ""; }
źródło
Poszedłbym z
boost::filesystem::extension
(std::filesystem::path::extension
z C ++ 17), ale jeśli nie możesz użyć Boost i musisz tylko zweryfikować rozszerzenie, prostym rozwiązaniem jest: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")) { /* ... */ }
źródło
To jest tylko Windows (Platform SDK)
źródło
To jest rozwiązanie, które wymyśliłem. Potem zauważyłem, że jest podobny do tego, co opublikował @serengeor.
Działa z
std::string
ifind_last_of
, ale podstawowa idea zadziała również, jeśli zostanie zmodyfikowana do używaniachar
tablic istrrchr
. Obsługuje ukryte pliki i dodatkowe kropki reprezentujące bieżący katalog. Jest niezależny od platformy.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. // e.g., a hidden file: ".alpha". // This test also incidentally avoids a dot that is really a current directory indicator. // e.g.: "alpha/./bravo" if ( dotIdx > dirSepIdx + 1 ) { ext = path.substr( dotIdx ); } } return ext; }
Test jednostkowy:
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; }
źródło
Używam tych dwóch funkcji, aby uzyskać rozszerzenie i nazwę pliku bez rozszerzenia :
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); }
I te
regex
podejścia dla pewnych dodatkowych wymagań: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; }
Dodatkowe wymagania, które spełnia metoda regex:
.config
lub podobna do tego, rozszerzenie będzie pustym ciągiem, a nazwa pliku bez rozszerzenia będzie.config
.EDYTOWAĆ:
Dodatkowe wymagania mogą być również spełnione przez:
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; }
Uwaga:
Przekaż tylko nazwy plików (nie ścieżki) w powyższych funkcjach.
źródło
Spróbuj użyć strstr
char* lastSlash; lastSlash = strstr(filename, ".");
źródło
Lub możesz użyć tego:
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; } } }
Ten kod jest wieloplatformowy
źródło
Jeśli korzystasz z biblioteki Qt, można dać spróbować QFileInfo jest przyrostkiem ()
źródło
Oto funkcja, która pobiera ścieżkę / nazwę pliku jako ciąg i zwraca rozszerzenie jako ciąg. To wszystko jest w standardzie C ++ i powinno działać na wielu platformach dla większości platform.
W przeciwieństwie do kilku innych odpowiedzi tutaj, obsługuje dziwne przypadki, które obsługuje PathFindExtension systemu Windows, na podstawie dokumentacji PathFindExtensions.
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 ); }
źródło
max( filename.rfind(L'\\'), filename.rfind(L'/') )
porówna dwie wartości bez znaku, jedną z nich może byćnpos
największa możliwa liczba całkowita bez znaku. Więc może wyglądać, że nie ma folderu, nawet jeśli tam jest!Jeśli korzystasz z bibliotek Poco , możesz:
#include <Poco/Path.h> ... std::string fileExt = Poco::Path("/home/user/myFile.abc").getExtension(); // == "abc"
źródło
Jeśli uznasz rozszerzenie za ostatnią kropkę i możliwe znaki po niej, ale tylko wtedy, gdy nie zawierają one znaku separatora katalogu, poniższa funkcja zwraca indeks początkowy rozszerzenia lub -1, jeśli nie znaleziono rozszerzenia. Kiedy już to masz, możesz robić, co chcesz, na przykład zdjąć rozszerzenie, zmienić, sprawdzić itp.
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; }
źródło
Użyłem funkcji PathFindExtension (), aby dowiedzieć się, czy jest to prawidłowy plik tif, czy nie.
#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; }
źródło
Możesz użyć strrchr (), aby znaleźć ostatnie wystąpienie plików rozszerzeń. (Kropka) i pobrać. (Kropka). Sprawdź na przykład poniższy kod.
#include<stdio.h> void GetFileExtension(const char* file_name) { int ext = '.'; const char* extension = NULL; extension = strrchr(file_name, ext); if(extension == NULL){ printf("Invalid extension encountered\n"); return; } printf("File extension is %s\n", extension); } int main() { const char* file_name = "c:\\.directoryname\\file.name.with.too.many.dots.ext"; GetFileExtension(file_name); return 0; }
źródło