문자열이 주어지면 "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;
}
}
return "Yes...";
확인하지 않고 말할 수 있습니다 . 솔루션이 다른 입력에 대해 작동해야 함을 의미합니다. 또 다른 카운터 예로서, 확장자가없는 단순히 "conf"라는 파일도 위의 경우 "Yes ..."를 반환합니다.
boost::filesystem
, 사용하기는 쉽지만 필요한 지원을 제공합니다. boost.org/doc/libs/1_55_0/libs/filesystem/doc/index.htm
가장 좋은 방법은이를 수행하는 코드를 작성하지 않고 기존 메서드를 호출하는 것입니다. 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"와 같은 문자열에서도 항상 확장자를 반환합니다. 확장자를 찾을 수 없으면 ""를 반환합니다.
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;
}
나는 이것을 완전히 테스트하지는 않았지만 작동해야한다고 생각합니다.
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 ++ 모두에서 작동합니다. 그리고 크로스 플랫폼.
strlen(extension)
에서 사용하십시오 for
. 그런 다음 문자가 일치하지 않으면 false를 반환합니다. 외부 for
루프는 참을 반환합니다.
좋은 답변이지만 대부분의 경우 몇 가지 문제가 있습니다. 우선 좋은 답변은 경로 제목이있는 완전한 파일 이름에 대해 작동해야하며, 또한 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"))
{ /* ... */ }
이것은 내가 생각해 낸 해결책입니다. 그런 다음 @serengeor가 게시 한 내용과 비슷하다는 것을 알았습니다.
std::string
및 find_last_of
에서 작동 하지만 char
배열 및 strrchr
. 숨겨진 파일과 현재 디렉토리를 나타내는 추가 점을 처리합니다. 플랫폼 독립적입니다.
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;
}
단위 테스트 :
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;
}
이 두 함수를 사용하여 확장자 없이 확장자 와 파일 이름 을 얻습니다 .
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;
}
노트 :
위의 함수에서 경로가 아닌 파일 이름 만 전달하십시오.
또는 이것을 사용할 수 있습니다.
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;
}
}
}
이 코드는 크로스 플랫폼입니다.
다음은 경로 / 파일 이름을 문자열로 취하고 확장자를 문자열로 반환하는 함수입니다. 모두 표준 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 );
}
max( filename.rfind(L'\\'), filename.rfind(L'/') )
두 개의 부호없는 값을 비교합니다. 그중 하나는 npos
가능한 가장 큰 부호없는 정수일 수 있습니다. 따라서 폴더가 있어도 폴더가없는 것처럼 보일 수 있습니다!
Poco 라이브러리 를 사용하는 경우 다음 을 수행 할 수 있습니다.
#include <Poco/Path.h>
...
std::string fileExt = Poco::Path("/home/user/myFile.abc").getExtension(); // == "abc"
확장자를 마지막 점과 그 뒤의 가능한 문자로 간주하지만 디렉토리 구분 문자를 포함하지 않는 경우에만 다음 함수는 확장자 시작 색인을 반환하거나 확장자가 없으면 -1을 반환합니다. 확장 프로그램을 제거하고 변경하고 확인하는 등 원하는 작업을 수행 할 수 있습니다.
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;
}
PathFindExtension () 함수를 사용하여 유효한 tif 파일인지 여부를 확인했습니다.
#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;
}
strrchr () 을 사용 하여. (점)의 마지막 항목을 찾고. (점) 기반 확장 파일을 가져올 수 있습니다. 예를 들어 아래 코드를 확인하십시오.
#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;
}