C ++의 문자열에서 파일 확장자를 얻는 방법
문자열이 주어지면 "filename.conf"
확장 부분을 확인하는 방법은 무엇입니까?
크로스 플랫폼 솔루션이 필요합니다.
하나 이상의 점이있는 파일 이름을 관리해야합니다. 예 : 또는에 c:\.directoryname\file.name.with.too.many.dots.ext
의해 올바르게 처리되지 않습니다 .strchr
find.
내가 가장 좋아하는 것은 확장 (경로) 기능이있는 부스트 파일 시스템 라이브러리 입니다.
이것이 너무 간단한 해결책입니까?
#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;
}
}
가장 좋은 방법은이를 수행하는 코드를 작성하지 않고 기존 메서드를 호출하는 것입니다. Windows에서는 PathFindExtension 메서드가 가장 간단합니다.
그렇다면 왜 직접 작성하지 않겠습니까?
자, strrchr 예제를 보시죠. "c : \ program files \ AppleGate.Net \ readme"문자열에서 그 방법을 사용하면 어떻게됩니까? ".Net \ readme"가 확장자입니까? 몇 가지 사례에서 작동하는 것을 작성하는 것은 쉽지만 모든 사례에서 작동하는 것을 작성하는 것은 훨씬 더 어려울 수 있습니다.
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 특정 기능을 활용하고 싶을 것입니다.
다른 누군가가 부스트를 언급했지만이 작업을 수행하기 위해 실제 코드를 추가하고 싶었습니다.
#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
실제로 STL은 많은 코드없이이 작업을 수행 할 수 있습니다. 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.abcdesmp3"와 같은 문자열에서도 항상 확장자를 반환합니다. 확장자를 찾을 수 없으면 ""를 반환합니다.
사실 가장 쉬운 방법은
char* ext;
ext = strrchr(filename,'.')
기억해야 할 한 가지 : '.'
파일 이름에 존재하지 않으면 ext는 NULL
.
C ++ 17과 그 std::filesystem::path::extension
(라이브러리가 boost :: filesystem의 후속 제품 임)를 사용하면 eg를 사용하는 것보다 더 표현력있는 문장을 만들 수 있습니다 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"
}
}
참조 표준 : 파일 시스템 :: 경로 : 줄기 , 표준 : : 파일 시스템 : 경로 : 파일 이름을 .
나는 이미 작동하는 코드가 있지만 어떤 경우에는 작동하지 않을 것이라는 것을 알았음에도 불구하고 오늘이 질문을 우연히 발견했습니다.
일부 사람들은 이미 외부 라이브러리 사용을 제안했지만 학습 목적으로 자체 코드를 작성하는 것을 선호합니다.
일부 답변에는 처음에 사용했던 방법 (마지막 "."찾기)이 포함되어 있지만 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;
}
나는 이것을 완전히 테스트하지는 않았지만 작동해야한다고 생각합니다.
std :: string의 find / rfind를 사용하면이 문제가 해결되지만, 경로를 많이 사용한다면 boost :: filesystem :: path를 살펴보아야합니다.
나는 그것이 고품질이고 잘 테스트되고 (오픈 소스 및 상업적으로) 무료이며 완전히 이식 가능한 라이브러리이기 때문에 boost를 제안합니다.
char 배열 유형 문자열의 경우 다음을 사용할 수 있습니다.
#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;
}
파일 이름 외에도 파일 경로를 처리 할 수 있습니다. C 및 C ++ 모두에서 작동합니다. 그리고 크로스 플랫폼.
좋은 답변이지만 대부분의 경우 몇 가지 문제가 있습니다. 우선 좋은 답변은 경로 제목이있는 완전한 파일 이름에 대해 작동해야하며, 또한 Linux 또는 Windows에서도 작동해야하거나 언급했듯이 크로스 플랫폼이어야한다고 생각합니다. 대부분의 답변 : 확장자가없는 파일 이름이지만 점이 포함 된 폴더 이름이있는 경로가있는 경우 함수는 올바른 확장자를 반환하지 못합니다. 일부 테스트 사례의 예는 다음과 같습니다.
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
" brian newman "제안은 filename1 및 filename4에 대해 실패합니다. 역방향 찾기를 기반으로하는 대부분의 다른 답변은 filename1에 대해 실패합니다. 소스에 다음 메서드를 포함하는 것이 좋습니다. 이것은 확장의 첫 번째 문자의 인덱스를 반환하는 함수이거나 찾을 수없는 경우 주어진 문자열의 길이입니다.
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;
}
아래와 같이 C ++ 애플리케이션에서 위의 코드를 사용할 수 있습니다.
std::string get_file_ext(const char* fileName)
{
return std::string(fileName).substr(find_ext_idx(fileName));
}
경우에 따라 폴더가 인수로 파일 이름에 제공되고 폴더 이름에 점이 포함 된 경우 함수는 폴더의 점 후행을 반환하므로 지정된 이름이 폴더 이름이 아닌 파일 이름인지 먼저 확인하는 것이 좋습니다.
System :: String을 사용하는 NET / CLI 버전
System::String^ GetFileExtension(System::String^ FileName)
{
int Ext=FileName->LastIndexOf('.');
if( Ext != -1 )
return FileName->Substring(Ext+1);
return "";
}
나는 boost::filesystem::extension
( std::filesystem::path::extension
C ++ 17로) 함께 갈 것이지만 Boost를 사용할 수없고 확장을 확인해야하는 경우 간단한 해결책은 다음과 같습니다.
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"))
{ /* ... */ }
_splitpath, _wsplitpath, _splitpath_s, _wsplitpath_w
Windows (Platform SDK) 전용입니다.
이 두 함수를 사용하여 확장자 없이 확장자 와 파일 이름 을 얻습니다 .
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);
}
regex
특정 추가 요구 사항에 대한 이러한 접근 방식 :
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;
}
regex 메소드로 충족되는 추가 요구 사항 :
- 경우 파일 이름이 비슷
.config
하거나 같은, 확장은 빈 문자열이 될 것이다 확장자가없는 파일 이름이 될 것입니다.config
. - 파일 이름에 확장자가없는 경우 확장자는 빈 문자열이되고 확장자 가 없는 파일 이름은 변경되지 않은 파일 이름이 됩니다.
편집하다:
추가 요구 사항은 다음과 같은 방법으로도 충족 될 수 있습니다.
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;
}
노트 :
위의 함수에서 경로가 아닌 파일 이름 만 전달하십시오.
strstr을 사용해보십시오
char* lastSlash;
lastSlash = strstr(filename, ".");
또는 이것을 사용할 수 있습니다.
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;
}
}
}
이 코드는 크로스 플랫폼입니다.
Qt 라이브러리를 사용하는 경우 QFileInfo 의 suffix () 시도해 볼 수 있습니다.
다음은 경로 / 파일 이름을 문자열로 취하고 확장자를 문자열로 반환하는 함수입니다. 모두 표준 C ++이며 대부분의 플랫폼에서 크로스 플랫폼으로 작동합니다.
여기의 여러 다른 답변과 달리 PathFindExtensions의 설명서를 기반으로 Windows의 PathFindExtension이 처리하는 이상한 경우를 처리합니다.
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 );
}
This is a solution I came up with. Then, I noticed that it is similar to what @serengeor posted.
It works with std::string
and find_last_of
, but the basic idea will also work if modified to use char
arrays and strrchr
. It handles hidden files, and extra dots 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.
// 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;
}
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;
}
If you happen to use Poco libraries you can do:
#include <Poco/Path.h>
...
std::string fileExt = Poco::Path("/home/user/myFile.abc").getExtension(); // == "abc"
If you consider the extension as the last dot and the possible characters after it, but only if they don't contain the directory separator character, the following function returns the extension starting index, or -1 if no extension found. When you have that you can do what ever you want, like strip 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;
}
I used PathFindExtension() function to know whether it 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;
}
참고 URL : https://stackoverflow.com/questions/51949/how-to-get-file-extension-from-string-in-c
'development' 카테고리의 다른 글
드롭 다운 목록 / 선택에 optgroup 중첩 (0) | 2020.10.23 |
---|---|
Vim에서 파일 찾기 (재귀 적 디렉토리 검색을 통해) (0) | 2020.10.23 |
NSDate를 사용하여 요일 가져 오기 (0) | 2020.10.22 |
iOS 8 앱에서 상태 표시 줄 숨기기 (0) | 2020.10.22 |
가장 좋아하는 MATLAB / Octave 프로그래밍 트릭은 무엇입니까? (0) | 2020.10.22 |