Wie kann ich die Liste der Dateien in einem Verzeichnis in meinem C- oder C ++ - Code ermitteln?
Ich darf den ls
Befehl nicht ausführen und die Ergebnisse in meinem Programm analysieren.
Wie kann ich die Liste der Dateien in einem Verzeichnis in meinem C- oder C ++ - Code ermitteln?
Ich darf den ls
Befehl nicht ausführen und die Ergebnisse in meinem Programm analysieren.
Antworten:
Bei kleinen und einfachen Aufgaben verwende ich keinen Boost, sondern dirent.h, das auch für Windows verfügbar ist:
DIR *dir;
struct dirent *ent;
if ((dir = opendir ("c:\\src\\")) != NULL) {
/* print all the files and directories within directory */
while ((ent = readdir (dir)) != NULL) {
printf ("%s\n", ent->d_name);
}
closedir (dir);
} else {
/* could not open directory */
perror ("");
return EXIT_FAILURE;
}
Es ist nur eine kleine Header-Datei und erledigt die meisten einfachen Dinge, die Sie benötigen, ohne einen großen vorlagenbasierten Ansatz wie Boost zu verwenden (nichts für ungut, ich mag Boost!).
Der Autor der Windows-Kompatibilitätsebene ist Toni Ronkko. In Unix ist es ein Standardheader.
UPDATE 2017 :
In C ++ 17 gibt es jetzt eine offizielle Möglichkeit, Dateien Ihres Dateisystems aufzulisten : std::filesystem
. Es gibt eine ausgezeichnete Antwort von Shreevardhan unten mit diesem Quellcode:
#include <string>
#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;
int main()
{
std::string path = "/path/to/directory";
for (const auto & entry : fs::directory_iterator(path))
std::cout << entry.path() << std::endl;
}
std::experimental::filesystem
, mit C ++ 17 gibt es std::filesystem
. Siehe Antwort von Shreevardhan unten. Es werden also keine Bibliotheken von Drittanbietern benötigt.
C ++ 17 hat jetzt eine std::filesystem::directory_iterator
, die als verwendet werden kann
#include <string>
#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;
int main() {
std::string path = "/path/to/directory";
for (const auto & entry : fs::directory_iterator(path))
std::cout << entry.path() << std::endl;
}
Auch std::filesystem::recursive_directory_iterator
kann iterieren Unterverzeichnisse als auch.
namespace fs = std::experimental::filesystem;
. Es scheint aber in Ordnung zu funktionieren.
std::filesystem::path
zu std::cout
, werden die Anführungszeichen in der Ausgabe enthalten. Um dies zu vermeiden, hängen Sie .string()
an den Pfad an, um eine explizite anstelle einer impliziten Konvertierung durchzuführen (hier std::cout << p.string() << std::endl;
). Beispiel: coliru.stacked-crooked.com/view?id=a55ea60bbd36a8a3
std::wstring
verwendet werden oder was ist der Typ vom Iterator?
-lstdc++fs
würde ich eine bekommen SIGSEGV (Address boundary error)
. Ich konnte nirgendwo in der Dokumentation feststellen, dass dies erforderlich war, und der Linker gab auch keinen Hinweis. Dies funktionierte sowohl für g++ 8.3.0
als auch clang 8.0.0-3
. Hat jemand einen Einblick, wo solche Dinge in den Dokumenten / Spezifikationen angegeben sind?
Leider definiert der C ++ - Standard keine Standardmethode für die Arbeit mit Dateien und Ordnern auf diese Weise.
Da es keinen plattformübergreifenden Weg gibt, ist es am besten, eine Bibliothek wie das Boost-Dateisystemmodul zu verwenden .
Plattformübergreifende Boost-Methode:
Die folgende Funktion durchsucht das Verzeichnis und seine Unterverzeichnisse unter Angabe eines Verzeichnispfads und eines Dateinamens rekursiv nach dem Dateinamen und gibt einen Bool und bei Erfolg den Pfad zu der gefundenen Datei zurück.
bool find_file(const path & dir_path, // in this directory, const std::string & file_name, // search for this name, path & path_found) // placing path here if found { if (!exists(dir_path)) return false; directory_iterator end_itr; // default construction yields past-the-end for (directory_iterator itr(dir_path); itr != end_itr; ++itr) { if (is_directory(itr->status())) { if (find_file(itr->path(), file_name, path_found)) return true; } else if (itr->leaf() == file_name) // see below { path_found = itr->path(); return true; } } return false; }
Quelle von der oben erwähnten Boost-Seite.
Für Unix / Linux-basierte Systeme:
Sie können opendir / readdir / closedir verwenden .
Beispielcode, der ein Verzeichnis nach dem Eintrag "Name" durchsucht, lautet:
len = strlen(name); dirp = opendir("."); while ((dp = readdir(dirp)) != NULL) if (dp->d_namlen == len && !strcmp(dp->d_name, name)) { (void)closedir(dirp); return FOUND; } (void)closedir(dirp); return NOT_FOUND;
Quellcode aus den obigen Manpages.
Für ein Windows-basiertes System:
Sie können die Win32-API-Funktionen FindFirstFile / FindNextFile / FindClose verwenden.
Das folgende C ++ - Beispiel zeigt Ihnen eine minimale Verwendung von FindFirstFile.
#include <windows.h> #include <tchar.h> #include <stdio.h> void _tmain(int argc, TCHAR *argv[]) { WIN32_FIND_DATA FindFileData; HANDLE hFind; if( argc != 2 ) { _tprintf(TEXT("Usage: %s [target_file]\n"), argv[0]); return; } _tprintf (TEXT("Target file is %s\n"), argv[1]); hFind = FindFirstFile(argv[1], &FindFileData); if (hFind == INVALID_HANDLE_VALUE) { printf ("FindFirstFile failed (%d)\n", GetLastError()); return; } else { _tprintf (TEXT("The first file found is %s\n"), FindFileData.cFileName); FindClose(hFind); } }
Quellcode von den obigen msdn-Seiten.
FindFirstFile(TEXT("D:\\IMAGE\\MYDIRECTORY\\*"), &findFileData);
std::experimental::filesystem
, mit C ++ 17 gibt std::filesystem
es ähnliche Funktionen wie boost (die Bibliotheken werden von boost abgeleitet). Siehe Antwort von Shreevardhan unten.
Eine Funktion reicht aus, Sie müssen keine Bibliothek eines Drittanbieters (für Windows) verwenden.
#include <Windows.h>
vector<string> get_all_files_names_within_folder(string folder)
{
vector<string> names;
string search_path = folder + "/*.*";
WIN32_FIND_DATA fd;
HANDLE hFind = ::FindFirstFile(search_path.c_str(), &fd);
if(hFind != INVALID_HANDLE_VALUE) {
do {
// read all (real) files in current folder
// , delete '!' read other 2 default folder . and ..
if(! (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) {
names.push_back(fd.cFileName);
}
}while(::FindNextFile(hFind, &fd));
::FindClose(hFind);
}
return names;
}
PS: Wie von @Sebastian erwähnt, können Sie zu wechseln *.*
, *.ext
um nur die EXT-Dateien (dh eines bestimmten Typs) in diesem Verzeichnis abzurufen .
std::vector<std::wstring>
und dann fileName.c_str()
anstelle eines Vektors von Zeichenfolgen verwendet, die nicht kompiliert werden konnten.
Überprüfen Sie dies für eine Nur-C-Lösung. Es ist nur ein zusätzlicher Header erforderlich:
https://github.com/cxong/tinydir
tinydir_dir dir;
tinydir_open(&dir, "/path/to/dir");
while (dir.has_next)
{
tinydir_file file;
tinydir_readfile(&dir, &file);
printf("%s", file.name);
if (file.is_dir)
{
printf("/");
}
printf("\n");
tinydir_next(&dir);
}
tinydir_close(&dir);
Einige Vorteile gegenüber anderen Optionen:
readdir_r
wo verfügbar, was bedeutet, dass es (normalerweise) threadsicher istUNICODE
MakrosIch empfehle die Verwendung glob
mit diesem wiederverwendbaren Wrapper. Es werden vector<string>
entsprechende Dateipfade generiert , die zum Glob-Muster passen:
#include <glob.h>
#include <vector>
using std::vector;
vector<string> globVector(const string& pattern){
glob_t glob_result;
glob(pattern.c_str(),GLOB_TILDE,NULL,&glob_result);
vector<string> files;
for(unsigned int i=0;i<glob_result.gl_pathc;++i){
files.push_back(string(glob_result.gl_pathv[i]));
}
globfree(&glob_result);
return files;
}
Was dann mit einem normalen System-Platzhaltermuster aufgerufen werden kann, wie zum Beispiel:
vector<string> files = globVector("./*");
No such file or directory
. Können Sie mir bitte sagen, wie ich dieses Problem lösen kann?
GLOB_TILDE
mit GLOB_TILDE | GLOB_MARK
Pfaden wechseln und dann nach Pfaden suchen, die mit einem Schrägstrich enden. Sie müssen beide Änderungen vornehmen, wenn Sie dies benötigen.
glob
.
Hier ist ein sehr einfacher Code für die C++11
Verwendung der boost::filesystem
Bibliothek zum Abrufen von Dateinamen in einem Verzeichnis (ohne Ordnernamen):
#include <string>
#include <iostream>
#include <boost/filesystem.hpp>
using namespace std;
using namespace boost::filesystem;
int main()
{
path p("D:/AnyFolder");
for (auto i = directory_iterator(p); i != directory_iterator(); i++)
{
if (!is_directory(i->path())) //we eliminate directories
{
cout << i->path().filename().string() << endl;
}
else
continue;
}
}
Die Ausgabe ist wie folgt:
file1.txt
file2.dat
boost::filesystem
Bibliothek boost.org/doc/libs/1_58_0/libs/filesystem/doc/index.htm
Warum nicht verwenden glob()
?
#include <glob.h>
glob_t glob_result;
glob("/your_directory/*",GLOB_TILDE,NULL,&glob_result);
for(unsigned int i=0; i<glob_result.gl_pathc; ++i){
cout << glob_result.gl_pathv[i] << endl;
}
Ich denke, das folgende Snippet kann verwendet werden, um alle Dateien aufzulisten.
#include <stdio.h>
#include <dirent.h>
#include <sys/types.h>
static void list_dir(const char *path)
{
struct dirent *entry;
DIR *dir = opendir(path);
if (dir == NULL) {
return;
}
while ((entry = readdir(dir)) != NULL) {
printf("%s\n",entry->d_name);
}
closedir(dir);
}
Es folgt die Struktur des Strukturverzeichnisses
struct dirent {
ino_t d_ino; /* inode number */
off_t d_off; /* offset to the next dirent */
unsigned short d_reclen; /* length of this record */
unsigned char d_type; /* type of file */
char d_name[256]; /* filename */
};
Versuchen Sie Boost für die X-Plattform-Methode
http://www.boost.org/doc/libs/1_38_0/libs/filesystem/doc/index.htm
oder verwenden Sie einfach Ihr betriebssystemspezifisches Dateimaterial.
Schauen Sie sich diese Klasse an, die die Win32-API verwendet. Erstellen foldername
Sie einfach eine Instanz, indem Sie die gewünschte Instanz angeben, und rufen Sie dann die getNextFile
Methode auf, um die nächste filename
aus dem Verzeichnis abzurufen. Ich denke es braucht windows.h
und stdio.h
.
class FileGetter{
WIN32_FIND_DATAA found;
HANDLE hfind;
char folderstar[255];
int chk;
public:
FileGetter(char* folder){
sprintf(folderstar,"%s\\*.*",folder);
hfind = FindFirstFileA(folderstar,&found);
//skip .
FindNextFileA(hfind,&found);
}
int getNextFile(char* fname){
//skips .. when called for the first time
chk=FindNextFileA(hfind,&found);
if (chk)
strcpy(fname, found.cFileName);
return chk;
}
};
GNU Handbuch FTW
Manchmal ist es auch gut, direkt zur Quelle zu gehen (Wortspiel beabsichtigt). Sie können viel lernen, indem Sie sich die Innereien einiger der häufigsten Befehle unter Linux ansehen. Ich habe einen einfachen Spiegel der GNU-Coreutils auf Github eingerichtet (zum Lesen).
https://github.com/homer6/gnu_coreutils/blob/master/src/ls.c
Möglicherweise wird Windows nicht angesprochen, aber mit diesen Methoden können einige Fälle der Verwendung von Unix-Varianten auftreten.
Ich hoffe, das hilft...
Shreevardhan Antwort funktioniert großartig. Wenn Sie es jedoch in C ++ 14 verwenden möchten, nehmen Sie einfach eine Änderung vornamespace fs = experimental::filesystem;
dh
#include <string>
#include <iostream>
#include <filesystem>
using namespace std;
namespace fs = experimental::filesystem;
int main()
{
string path = "C:\\splits\\";
for (auto & p : fs::directory_iterator(path))
cout << p << endl;
int n;
cin >> n;
}
char **getKeys(char *data_dir, char* tablename, int *num_keys)
{
char** arr = malloc(MAX_RECORDS_PER_TABLE*sizeof(char*));
int i = 0;
for (;i < MAX_RECORDS_PER_TABLE; i++)
arr[i] = malloc( (MAX_KEY_LEN+1) * sizeof(char) );
char *buf = (char *)malloc( (MAX_KEY_LEN+1)*sizeof(char) );
snprintf(buf, MAX_KEY_LEN+1, "%s/%s", data_dir, tablename);
DIR* tableDir = opendir(buf);
struct dirent* getInfo;
readdir(tableDir); // ignore '.'
readdir(tableDir); // ignore '..'
i = 0;
while(1)
{
getInfo = readdir(tableDir);
if (getInfo == 0)
break;
strcpy(arr[i++], getInfo->d_name);
}
*(num_keys) = i;
return arr;
}
Ich hoffe dieser Code hilft Ihnen.
#include <windows.h>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
string wchar_t2string(const wchar_t *wchar)
{
string str = "";
int index = 0;
while(wchar[index] != 0)
{
str += (char)wchar[index];
++index;
}
return str;
}
wchar_t *string2wchar_t(const string &str)
{
wchar_t wchar[260];
int index = 0;
while(index < str.size())
{
wchar[index] = (wchar_t)str[index];
++index;
}
wchar[index] = 0;
return wchar;
}
vector<string> listFilesInDirectory(string directoryName)
{
WIN32_FIND_DATA FindFileData;
wchar_t * FileName = string2wchar_t(directoryName);
HANDLE hFind = FindFirstFile(FileName, &FindFileData);
vector<string> listFileNames;
listFileNames.push_back(wchar_t2string(FindFileData.cFileName));
while (FindNextFile(hFind, &FindFileData))
listFileNames.push_back(wchar_t2string(FindFileData.cFileName));
return listFileNames;
}
void main()
{
vector<string> listFiles;
listFiles = listFilesInDirectory("C:\\*.txt");
for each (string str in listFiles)
cout << str << endl;
}
string2wchar_t
Gibt die Adresse einer lokalen Variablen zurück. Außerdem sollten Sie wahrscheinlich die in WinAPI verfügbaren Konvertierungsmethoden verwenden, anstatt Ihre eigenen zu schreiben.
Diese Implementierung verwirklicht Ihren Zweck und füllt dynamisch ein Array von Zeichenfolgen mit dem Inhalt des angegebenen Verzeichnisses.
int exploreDirectory(const char *dirpath, char ***list, int *numItems) {
struct dirent **direntList;
int i;
errno = 0;
if ((*numItems = scandir(dirpath, &direntList, NULL, alphasort)) == -1)
return errno;
if (!((*list) = malloc(sizeof(char *) * (*numItems)))) {
fprintf(stderr, "Error in list allocation for file list: dirpath=%s.\n", dirpath);
exit(EXIT_FAILURE);
}
for (i = 0; i < *numItems; i++) {
(*list)[i] = stringDuplication(direntList[i]->d_name);
}
for (i = 0; i < *numItems; i++) {
free(direntList[i]);
}
free(direntList);
return 0;
}
if
Block auszuführen . Ich rufe es mitchar **list; int numItems; exploreDirectory("/folder",list, numItems);
Das funktioniert bei mir. Es tut mir leid, wenn ich mich nicht an die Quelle erinnern kann. Es ist wahrscheinlich von einer Manpage.
#include <ftw.h>
int AnalizeDirectoryElement (const char *fpath,
const struct stat *sb,
int tflag,
struct FTW *ftwbuf) {
if (tflag == FTW_F) {
std::string strFileName(fpath);
DoSomethingWith(strFileName);
}
return 0;
}
void WalkDirectoryTree (const char * pchFileName) {
int nFlags = 0;
if (nftw(pchFileName, AnalizeDirectoryElement, 20, nFlags) == -1) {
perror("nftw");
}
}
int main() {
WalkDirectoryTree("some_dir/");
}
Mit std :: experimental :: filesystem :: directory_iterator () können Sie alle Dateien direkt in Ihrem Stammverzeichnis abrufen. Lesen Sie dann den Namen dieser Pfaddateien.
#include <iostream>
#include <filesystem>
#include <string>
#include <direct.h>
using namespace std;
namespace fs = std::experimental::filesystem;
void ShowListFile(string path)
{
for(auto &p: fs::directory_iterator(path)) /*get directory */
cout<<p.path().filename()<<endl; // get file name
}
int main() {
ShowListFile("C:/Users/dell/Pictures/Camera Roll/");
getchar();
return 0;
}
Diese Antwort sollte für Windows-Benutzer funktionieren, bei denen Probleme mit Visual Studio mit einer der anderen Antworten aufgetreten sind.
Laden Sie die Datei dirent.h von der Github-Seite herunter. Es ist jedoch besser, einfach die Datei Raw dirent.h zu verwenden und die folgenden Schritte auszuführen (so habe ich sie zum Laufen gebracht).
Github-Seite für dirent.h für Windows: Github-Seite für dirent.h
Raw Dirent-Datei: Raw dirent.h-Datei
Gehen Sie zu Ihrem Projekt und fügen Sie ein neues Element hinzu ( Ctrl+ Shift+ A). Fügen Sie eine Header-Datei (.h) hinzu und nennen Sie sie dirent.h.
Fügen Sie den Raw dirent.h Datei - Code in der Kopfzeile.
Fügen Sie "dirent.h" in Ihren Code ein.
Fügen Sie die folgende void filefinder()
Methode in Ihren Code ein und rufen Sie sie von Ihrer main
Funktion aus auf oder bearbeiten Sie die Funktion so, wie Sie sie verwenden möchten.
#include <stdio.h>
#include <string.h>
#include "dirent.h"
string path = "C:/folder"; //Put a valid path here for folder
void filefinder()
{
DIR *directory = opendir(path.c_str());
struct dirent *direntStruct;
if (directory != NULL) {
while (direntStruct = readdir(directory)) {
printf("File Name: %s\n", direntStruct->d_name); //If you are using <stdio.h>
//std::cout << direntStruct->d_name << std::endl; //If you are using <iostream>
}
}
closedir(directory);
}
System nennen es!
system( "dir /b /s /a-d * > file_names.txt" );
Dann lesen Sie einfach die Datei.
BEARBEITEN: Diese Antwort sollte als Hack betrachtet werden, aber sie funktioniert wirklich (wenn auch plattformspezifisch), wenn Sie keinen Zugang zu eleganteren Lösungen haben.
Da Dateien und Unterverzeichnisse eines Verzeichnisses im Allgemeinen in einer Baumstruktur gespeichert sind, besteht eine intuitive Möglichkeit darin, den DFS-Algorithmus zu verwenden, um jedes von ihnen rekursiv zu durchlaufen. Hier ist ein Beispiel für ein Windows-Betriebssystem unter Verwendung der grundlegenden Dateifunktionen in io.h. Sie können diese Funktionen auf einer anderen Plattform ersetzen. Was ich ausdrücken möchte, ist, dass die Grundidee von DFS dieses Problem perfekt erfüllt.
#include<io.h>
#include<iostream.h>
#include<string>
using namespace std;
void TraverseFilesUsingDFS(const string& folder_path){
_finddata_t file_info;
string any_file_pattern = folder_path + "\\*";
intptr_t handle = _findfirst(any_file_pattern.c_str(),&file_info);
//If folder_path exsist, using any_file_pattern will find at least two files "." and "..",
//of which "." means current dir and ".." means parent dir
if (handle == -1){
cerr << "folder path not exist: " << folder_path << endl;
exit(-1);
}
//iteratively check each file or sub_directory in current folder
do{
string file_name=file_info.name; //from char array to string
//check whtether it is a sub direcotry or a file
if (file_info.attrib & _A_SUBDIR){
if (file_name != "." && file_name != ".."){
string sub_folder_path = folder_path + "\\" + file_name;
TraverseFilesUsingDFS(sub_folder_path);
cout << "a sub_folder path: " << sub_folder_path << endl;
}
}
else
cout << "file name: " << file_name << endl;
} while (_findnext(handle, &file_info) == 0);
//
_findclose(handle);
}
Ich habe versucht, dem Beispiel in beiden Antworten zu folgen, und es könnte erwähnenswert sein, dass es so aussieht, als ob std::filesystem::directory_entry
es geändert wurde, um keine Überlastung des <<
Operators zu haben. Stattdessen musste std::cout << p << std::endl;
ich Folgendes verwenden, um es kompilieren und zum Laufen bringen zu können:
#include <iostream>
#include <filesystem>
#include <string>
namespace fs = std::filesystem;
int main() {
std::string path = "/path/to/directory";
for(const auto& p : fs::directory_iterator(path))
std::cout << p.path() << std::endl;
}
Der Versuch, sich selbst weiterzugeben p
, std::cout <<
führte zu einem fehlenden Überlastungsfehler.
Aufbauend auf dem, was herohuyongtao gepostet hat, und einigen anderen Posts:
http://www.cplusplus.com/forum/general/39766/
Was ist der erwartete Eingabetyp von FindFirstFile?
Wie konvertiere ich wstring in string?
Dies ist eine Windows-Lösung.
Da ich std :: string übergeben und einen Vektor von Strings zurückgeben wollte, musste ich einige Konvertierungen vornehmen.
#include <string>
#include <Windows.h>
#include <vector>
#include <locale>
#include <codecvt>
std::vector<std::string> listFilesInDir(std::string path)
{
std::vector<std::string> names;
//Convert string to wstring
std::wstring search_path = std::wstring_convert<std::codecvt_utf8<wchar_t>>().from_bytes(path);
WIN32_FIND_DATA fd;
HANDLE hFind = FindFirstFile(search_path.c_str(), &fd);
if (hFind != INVALID_HANDLE_VALUE)
{
do
{
// read all (real) files in current folder
// , delete '!' read other 2 default folder . and ..
if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
//convert from wide char to narrow char array
char ch[260];
char DefChar = ' ';
WideCharToMultiByte(CP_ACP, 0, fd.cFileName, -1, ch, 260, &DefChar, NULL);
names.push_back(ch);
}
}
while (::FindNextFile(hFind, &fd));
::FindClose(hFind);
}
return names;
}
WIN32_FIND_DATAA
, können Sie FindFirstFileA
und verwenden FindNextFileA
. Dann müssen Sie das Ergebnis nicht in Multibyte oder die Eingabe in Unicode konvertieren.
Nur etwas, das ich teilen möchte und danke für das Lesematerial. Spielen Sie ein bisschen mit der Funktion herum, um sie zu verstehen. Es könnte dir gefallen. e stand für Erweiterung, p steht für Pfad und s steht für Pfadtrennzeichen.
Wenn der Pfad ohne Ende des Trennzeichens übergeben wird, wird ein Trennzeichen an den Pfad angehängt. Wenn für die Erweiterung eine leere Zeichenfolge eingegeben wird, gibt die Funktion alle Dateien zurück, deren Name keine Erweiterung enthält. Wenn ein einzelner Stern eingegeben wurde, werden alle Dateien im Verzeichnis zurückgegeben. Wenn die Länge e größer als 0 ist, aber kein einzelnes * ist, wird e ein Punkt vorangestellt, wenn e keinen Punkt an der Nullposition enthalten hat.
Für einen Rückgabewert. Wenn eine Karte mit der Länge Null zurückgegeben wird, wurde nichts gefunden, aber das Verzeichnis war in Ordnung geöffnet. Wenn der Index 999 über den Rückgabewert verfügbar ist, die Kartengröße jedoch nur 1 beträgt, bedeutet dies, dass beim Öffnen des Verzeichnispfads ein Problem aufgetreten ist.
Beachten Sie, dass diese Funktion aus Effizienzgründen in drei kleinere Funktionen unterteilt werden kann. Darüber hinaus können Sie eine Aufruferfunktion erstellen, die anhand der Eingabe erkennt, welche Funktion aufgerufen werden soll. Warum ist das effizienter? Wenn Sie alles abrufen möchten, was eine Datei ist, wird bei dieser Methode die Unterfunktion, die zum Abrufen aller Dateien erstellt wurde, nur alle Dateien abrufen und muss nicht jedes Mal, wenn eine Datei gefunden wird, eine andere unnötige Bedingung auswerten.
Dies gilt auch, wenn Sie Dateien abrufen, die keine Erweiterung haben. Eine bestimmte zu diesem Zweck erstellte Funktion würde nur dann das Wetter bewerten, wenn es sich bei dem gefundenen Objekt um eine Datei handelt und ob der Name der Datei einen Punkt enthält oder nicht.
Das Speichern ist möglicherweise nicht viel, wenn Sie nur Verzeichnisse mit weniger Dateien lesen. Wenn Sie jedoch eine große Menge an Verzeichnissen lesen oder wenn das Verzeichnis einige hunderttausend Dateien enthält, kann dies eine enorme Einsparung bedeuten.
#include <stdio.h>
#include <sys/stat.h>
#include <iostream>
#include <dirent.h>
#include <map>
std::map<int, std::string> getFile(std::string p, std::string e = "", unsigned char s = '/'){
if ( p.size() > 0 ){
if (p.back() != s) p += s;
}
if ( e.size() > 0 ){
if ( e.at(0) != '.' && !(e.size() == 1 && e.at(0) == '*') ) e = "." + e;
}
DIR *dir;
struct dirent *ent;
struct stat sb;
std::map<int, std::string> r = {{999, "FAILED"}};
std::string temp;
int f = 0;
bool fd;
if ( (dir = opendir(p.c_str())) != NULL ){
r.erase (999);
while ((ent = readdir (dir)) != NULL){
temp = ent->d_name;
fd = temp.find(".") != std::string::npos? true : false;
temp = p + temp;
if (stat(temp.c_str(), &sb) == 0 && S_ISREG(sb.st_mode)){
if ( e.size() == 1 && e.at(0) == '*' ){
r[f] = temp;
f++;
} else {
if (e.size() == 0){
if ( fd == false ){
r[f] = temp;
f++;
}
continue;
}
if (e.size() > temp.size()) continue;
if ( temp.substr(temp.size() - e.size()) == e ){
r[f] = temp;
f++;
}
}
}
}
closedir(dir);
return r;
} else {
return r;
}
}
void printMap(auto &m){
for (const auto &p : m) {
std::cout << "m[" << p.first << "] = " << p.second << std::endl;
}
}
int main(){
std::map<int, std::string> k = getFile("./", "");
printMap(k);
return 0;
}
#include<iostream>
#include <dirent.h>
using namespace std;
char ROOT[]={'.'};
void listfiles(char* path){
DIR * dirp = opendir(path);
dirent * dp;
while ( (dp = readdir(dirp)) !=NULL ) {
cout << dp->d_name << " size " << dp->d_reclen<<std::endl;
}
(void)closedir(dirp);
}
int main(int argc, char **argv)
{
char* path;
if (argc>1) path=argv[1]; else path=ROOT;
cout<<"list files in ["<<path<<"]"<<std::endl;
listfiles(path);
return 0;
}
Das hat bei mir funktioniert. Es schreibt eine Datei mit nur den Namen (kein Pfad) aller Dateien. Dann liest es diese txt-Datei und druckt sie für Sie aus.
void DisplayFolderContent()
{
system("dir /n /b * > file_names.txt");
char ch;
std::fstream myStream("file_names.txt", std::fstream::in);
while (myStream.get(ch))
{
std::cout << ch;
}
}