Ik heb een lijst met bestanden die zijn opgeslagen in een .log
in deze syntaxis:
c:\foto\foto2003\shadow.gif
D:\etc\mom.jpg
Ik wil de naam en de extensie uit deze bestanden halen. Kun je een voorbeeld geven van een eenvoudige manier om dit te doen?
Antwoord 1, autoriteit 100%
Om een bestandsnaam zonder extensie te extraheren, gebruik je boost::filesystem::path::stemin plaats van lelijke std::string::find_last_of(“.”)
boost::filesystem::path p("c:/dir/dir/file.ext");
std::cout << "filename and extension : " << p.filename() << std::endl; // file.ext
std::cout << "filename only : " << p.stem() << std::endl; // file
Antwoord 2, autoriteit 21%
Voor C++17:
#include <filesystem>
std::filesystem::path p("c:/dir/dir/file.ext");
std::cout << "filename and extension: " << p.filename() << std::endl; // "file.ext"
std::cout << "filename only: " << p.stem() << std::endl; // "file"
Referentie over bestandssysteem: http://en.cppreference.com/w/cpp/filesystem
Zoals gesuggereerd door @RoiDanto, kan std::out
voor de uitvoeropmaak de uitvoer tussen aanhalingstekens plaatsen, bijvoorbeeld:
filename and extension: "file.ext"
Je kunt std::filesystem::path
naar std::string
converteren door p.filename().string()
als dat is wat je nodig hebt, bijvoorbeeld:
filename and extension: file.ext
Antwoord 3, autoriteit 9%
Als je een veilige manier wilt (d.w.z. draagbaar tussen platforms en geen aannames op het pad plaatst), raad ik aan om boost::filesystem
te gebruiken.
Het zou er ongeveer zo uitzien:
boost::filesystem::path my_path( filename );
Vervolgens kunt u verschillende gegevens uit dit pad halen. Hier is de documentatie van het path-object.
BTW: onthoud ook dat om het pad te gebruiken zoals
c:\foto\foto2003\shadow.gif
je moet de \
escapen in een letterlijke tekenreeks:
const char* filename = "c:\\foto\\foto2003\\shadow.gif";
Of gebruik in plaats daarvan /
:
const char* filename = "c:/foto/foto2003/shadow.gif";
Dit is alleen van toepassing op het specificeren van letterlijke tekenreeksen tussen ""
aanhalingstekens, het probleem bestaat niet wanneer u paden uit een bestand laadt.
Antwoord 4, autoriteit 9%
Je moet je bestandsnamen lezen uit het bestand in std::string
. U kunt de tekenreeksextractie-operator van std::ostream
gebruiken. Zodra je bestandsnaam in een std::string
staat, kun je de std::string::find_last_of
methode gebruiken om het laatste scheidingsteken te vinden.
Zoiets:
std::ifstream input("file.log");
while (input)
{
std::string path;
input >> path;
size_t sep = path.find_last_of("\\/");
if (sep != std::string::npos)
path = path.substr(sep + 1, path.size() - sep - 1);
size_t dot = path.find_last_of(".");
if (dot != std::string::npos)
{
std::string name = path.substr(0, dot);
std::string ext = path.substr(dot, path.size() - dot);
}
else
{
std::string name = path;
std::string ext = "";
}
}
Antwoord 5, autoriteit 2%
Niet de code, maar hier is het idee:
- Lees een
std::string
uit de invoerstroom (std::ifstream
), elke gelezen instantie is het volledige pad - Voer een
find_last_of
uit op de string voor de\
- Extract een substring van deze positie tot het einde, dit geeft je nu de bestandsnaam
- Doe een
find_last_of
voor.
, en een substring aan weerszijden geeft je naam + extensie.
Antwoord 6
De volgende truc om de bestandsnaam te extraheren uit een bestandspad zonder extensie in c++ (geen externe bibliotheken vereist):
#include <iostream>
#include <string>
using std::string;
string getFileName(const string& s) {
char sep = '/';
#ifdef _WIN32
sep = '\\';
#endif
size_t i = s.rfind(sep, s.length());
if (i != string::npos)
{
string filename = s.substr(i+1, s.length() - i);
size_t lastindex = filename.find_last_of(".");
string rawname = filename.substr(0, lastindex);
return(rawname);
}
return("");
}
int main(int argc, char** argv) {
string path = "/home/aymen/hello_world.cpp";
string ss = getFileName(path);
std::cout << "The file name is \"" << ss << "\"\n";
}
Antwoord 7
Ik gebruik dit fragment ook om de juiste schuine streep te bepalen:
boost::filesystem::path slash("/");
boost::filesystem::path::string_type preferredSlash = slash.make_preferred().native();
en vervang de schuine streep door de gewenste schuine streep voor het besturingssysteem. Handig als men constant aan het implementeren is tussen Linux/Windows.
Antwoord 8
Voor linux- of unix-machines heeft het besturingssysteem twee functies voor pad- en bestandsnamen. gebruik man 3 basename om meer informatie over deze functies te krijgen.
Het voordeel van het gebruik van de door het systeem geleverde functionaliteit is dat u geen boost hoeft te installeren of uw eigen functies hoeft te schrijven.
#include <libgen.h>
char *dirname(char *path);
char *basename(char *path);
Voorbeeldcode van de man-pagina:
char *dirc, *basec, *bname, *dname;
char *path = "/etc/passwd";
dirc = strdup(path);
basec = strdup(path);
dname = dirname(dirc);
bname = basename(basec);
printf("dirname=%s, basename=%s\n", dname, bname);
Vanwege het niet-const-argumenttype van de functie basename() is het een beetje niet eenvoudig om dit in C++-code te gebruiken. Hier is een eenvoudig voorbeeld uit mijn codebasis:
string getFileStem(const string& filePath) const {
char* buff = new char[filePath.size()+1];
strcpy(buff, filePath.c_str());
string tmp = string(basename(buff));
string::size_type i = tmp.rfind('.');
if (i != string::npos) {
tmp = tmp.substr(0,i);
}
delete[] buff;
return tmp;
}
Het gebruik van nieuw/verwijder is geen goede stijl. Ik had het in een try/catch kunnen zetten
blokkeren voor het geval er iets tussen de twee gesprekken is gebeurd.
Antwoord 9
De antwoorden van Nickolay Merkin en Yuchen Zhong zijn geweldig, maar uit de opmerkingen kun je zien dat het niet helemaal juist is.
De impliciete conversie naar std::string bij het afdrukken plaatst de bestandsnaam tussen aanhalingstekens. De opmerkingen zijn ook niet correct.
path::filename()
en path::stem()
retourneert een nieuw path-object en path::string()
retourneert een verwijzing naar een string. Dus zoiets als std::cout << file_path.filename().string() << "\n"
kan problemen veroorzaken met bungelende referentie, aangezien de string waarnaar de referentie verwijst mogelijk is vernietigd.