Come ottenere estensione del file da stringa in C ++

voti
67

Data una stringa di filename.conf, come verifico parte di prolungamento?

Ho bisogno di una soluzione cross platform.

È pubblicato 09/09/2008 alle 14:57
fonte dall'utente
In altre lingue...                            


24 risposte

voti
123

È questo troppo semplice di una soluzione?

#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;
  }
}
Risposto il 09/09/2008 a 15:23
fonte dall'utente

voti
39

Il modo migliore è di non scrivere alcun codice che lo fa, ma chiamare i metodi esistenti. In Windows, il PathFindExtension metodo è probabilmente il più semplice.

Allora perché non scrivere il proprio?

Beh, prendere l'esempio strrchr, che cosa succede quando si utilizza questo metodo sul seguente stringa "c: \ program files \ AppleGate.Net \ readme"? ".Net \ readme" è l'estensione? E 'facile scrivere qualcosa che funziona per un paio di casi di esempio, ma può essere molto più difficile da scrivere qualcosa che funziona per tutti i casi.

Risposto il 09/09/2008 a 15:20
fonte dall'utente

voti
32

È necessario assicurarsi che si prende cura di nomi di file con più di un punto. Esempio: c:\.directoryname\file.name.with.too.many.dots.extnon sarebbe stato gestito correttamente dal strchrofind.

Il mio preferito sarebbe la libreria Boost filesystem che hanno una funzione di estensione (percorso)

Risposto il 09/09/2008 a 15:27
fonte dall'utente

voti
26

Supponendo di avere accesso a 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: Questa è una soluzione cross-platform dal momento che non ha citato la piattaforma. Se siete particolare su Windows, ti consigliamo di sfruttare le funzioni specifiche di Windows detto da altri nel thread.

Risposto il 09/09/2008 a 15:20
fonte dall'utente

voti
21

Qualcun altro ha menzionato spinta, ma volevo solo aggiungere il codice vero e proprio per fare questo:

#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
Risposto il 09/10/2012 a 03:46
fonte dall'utente

voti
17

in realtà lo STL può fare questo senza molto codice, vi consiglio di imparare un po 'circa la STL, perché permette di fare alcune cose di fantasia, comunque questo è quello che uso.

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

questa soluzione restituirà sempre l'estensione anche su stringhe come "this.abcdesmp3" se non riesce a trovare l'estensione tornerà "".

Risposto il 22/12/2010 a 04:30
fonte dall'utente

voti
8

In realtà, il modo più semplice è

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

Una cosa da ricordare: se '.'non esiste nel nome del file, ext sarà NULL.

Risposto il 30/07/2013 a 11:26
fonte dall'utente

voti
5

Ho inciampato su questa domanda oggi me stesso, anche se avevo già un codice di lavoro ho capito che non avrebbe funzionato in alcuni casi.

Mentre alcune persone già suggerito l'utilizzo di alcune librerie esterne, preferisco scrivere il mio codice a fini di apprendimento.

Alcune risposte incluso il metodo che usavo in primo luogo (che cerca l'ultimo " '), ma mi sono ricordato che il file nascosti linux / cartelle iniziano con'.". Quindi, se il file file è nascosto e non ha alcuna estensione, l'intero nome del file sarebbe stata presa per l'estensione. Per evitare che ho scritto questo pezzo di codice:

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

Non ho ancora testato questo completamente, ma penso che dovrebbe funzionare.

Risposto il 17/11/2012 a 12:26
fonte dall'utente

voti
4
_splitpath, _wsplitpath, _splitpath_s, _wsplitpath_w

Penso che questo sia di Windows (Platform SDK) solo?

Risposto il 09/09/2008 a 15:03
fonte dall'utente

voti
3

Le buone risposte, ma vedo la maggior parte di loro ha qualche problema: Prima di tutto penso che una buona risposta dovrebbe funzionare per i nomi di file completi che hanno le loro intestazioni di percorso, anche dovrebbe funzionare per Linux o Windows o come detto dovrebbe essere cross-platform. Per la maggior parte delle risposte; i nomi dei file senza estensione, ma un percorso con un nome di cartella compreso punto, la funzione non riuscirà a tornare l'estensione corretta: esempi di alcuni casi di test potrebbero essere i seguenti:

    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 " suggerimento fallirà per nomefile1 e filename4. e la maggior parte delle altre risposte che si basano su find rovescio falliranno per nomefile1. Suggerisco incluso il seguente metodo nella fonte: che è funzione che restituisce indice del primo carattere della proroga o la lunghezza della stringa specificata se non trovato.

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

è possibile utilizzare il codice di cui sopra nella vostra applicazione C ++ come qui di seguito:

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

L'ultimo punto, in alcuni casi è data la cartella al nome del file come argomento e include un puntino nella cartella un nome alla funzione restituirà punto della cartella in svantaggio quindi meglio primo a controllo utente che il nome dato è un nome di file e non Nome cartella.

Risposto il 08/11/2014 a 22:49
fonte dall'utente

voti
3

Una versione NET / CLI using System :: String

   System::String^ GetFileExtension(System::String^ FileName)
   {
       int Ext=FileName->LastIndexOf('.');
       if( Ext != -1 )
           return FileName->Substring(Ext+1);
       return "";
   }
Risposto il 25/07/2011 a 21:05
fonte dall'utente

voti
3

Per char stringhe array-tipo è possibile utilizzare questo:

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

In grado di gestire i percorsi di file, oltre ai nomi dei file. Funziona sia con C e C ++. E cross-platform.

Risposto il 24/01/2011 a 00:49
fonte dall'utente

voti
3

Usando di std :: string find / rfind risolve questo problema, ma se si lavora molto con i percorsi allora si dovrebbe guardare boost :: filesystem :: percorso dal momento che rendere il codice molto più pulito di giocherellare con prime stringa indici / iteratori.

Suggerisco spinta dal momento che è una qualità elevata, ben collaudato, (open source e in commercio) biblioteca libera e completamente portatile.

Risposto il 13/12/2009 a 22:34
fonte dall'utente

voti
2

Io uso queste due funzioni per ottenere il prolungamento e il nome del file senza estensione :

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

E questi regexapprocci per determinati requisiti aggiuntivi:

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;

}

requisiti aggiuntivi che si incontrano con il metodo di espressione regolare:

  1. Se il nome del file è come .configo qualcosa di simile, estensione sarà una stringa vuota e il nome del file senza estensione sarà .config.
  2. Se nomefile non ha alcuna estensione, estensione sarà una stringa vuota, il nome del file senza estensione sarà il nome del file invariato.

MODIFICARE:

I requisiti aggiuntivi possono essere soddisfatti anche dal seguente:

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

Nota:

Passare solo i nomi dei file (non dei percorsi) nelle funzioni di cui sopra.

Risposto il 19/08/2015 a 20:03
fonte dall'utente

voti
2

Mi piacerebbe andare con boost::filesystem::extension, ma se non è possibile utilizzare Boost e basta verificare l'estensione, una soluzione semplice è:

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"))
{ /* ... */ }
Risposto il 02/05/2015 a 17:14
fonte dall'utente

voti
1

Con C ++ 17 e la sua std::filesystem::path::extension(la biblioteca è il successore di boost :: filesystem) si dovrebbe fare la sua dichiarazione più espressiva che utilizza per esempio 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"
    }
}

Vedi anche std :: filesystem :: :: percorso gambo , std :: filesystem :: :: percorso il nome del file .

Risposto il 15/06/2018 a 19:28
fonte dall'utente

voti
1

Questa è una soluzione mi è venuta. Poi, ho notato che è simile a quello che @serengeor pubblicato.

Funziona con std::stringe find_last_of, ma l'idea di base funziona anche se modificati per utilizzare charle matrici e strrchr. Gestisce i file nascosti, e punti in più che rappresentano la directory corrente. E 'indipendente dalla piattaforma.

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à di prova:

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;
}
Risposto il 19/08/2015 a 21:20
fonte dall'utente

voti
1

Ecco una funzione che prende un percorso / nomefile come una stringa e restituisce l'estensione come una stringa. Si tratta di tutti gli standard C ++, e dovrebbe funzionare cross-platform per la maggior parte delle piattaforme.

A differenza di molte altre risposte qui, gestisce i casi strani che maniglie PathFindExtension finestre, sulla base della documentazione di 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 );
}
Risposto il 28/04/2014 a 17:51
fonte dall'utente

voti
1

Se si utilizza librerie Qt, si può dare una prova di QFileInfo s' il suffisso ()

Risposto il 02/03/2014 a 12:03
fonte dall'utente

voti
1

Oppure si può usare questo:

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

Questo codice è cross-platform

Risposto il 07/08/2013 a 11:13
fonte dall'utente

voti
1

Cercate di usare strstr

char* lastSlash;
lastSlash = strstr(filename, ".");
Risposto il 11/05/2012 a 08:56
fonte dall'utente

voti
0

Ho usato la funzione PathFindExtension () per sapere se si tratta di un file tif valido o meno.

#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;
}
Risposto il 20/01/2016 a 17:24
fonte dall'utente

voti
0

Se si considera l'estensione come l'ultimo punto e le possibili caratteri dopo di esso, ma solo se non contengono il carattere separatore di directory, la seguente funzione restituisce l'estensione di partenza dell'indice, oppure -1 se nessuna estensione trovato. Quando si dispone che si può fare quello che vuoi, come spogliare l'estensione, modificarlo, controllarlo 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;
}
Risposto il 17/12/2015 a 10:59
fonte dall'utente

voti
0

Se vi capita di usare Poco librerie si può fare:

#include <Poco/Path.h>

...

std::string fileExt = Poco::Path("/home/user/myFile.abc").getExtension(); // == "abc"
Risposto il 16/11/2015 a 06:46
fonte dall'utente

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more