@chrish - Tak, ale ten ma klasyczne „Nie wolno mi wykonywać„ ls ”! To dokładnie jak czułbym 1 roku informatyki. ; D <3 x
James Bedford
1
C i C ++ nie są tym samym językiem. Dlatego procedura wykonania tego zadania będzie różna w obu językach. Wybierz jeden i odpowiednio ponownie otaguj.
MD XF,
2
I żaden z tych języków (inny niż C ++ od C ++ 17) nie ma nawet pojęcia katalogu - więc każda odpowiedź prawdopodobnie będzie zależała od twojego systemu operacyjnego lub bibliotek abstrakcyjnych, których możesz używać.
Toby Speight
Odpowiedzi:
809
W małych i prostych zadaniach nie używam doładowania, używam dirent.h, który jest również dostępny dla systemu Windows:
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;}
Jest to tylko mały plik nagłówkowy i wykonuje większość prostych czynności, których potrzebujesz, bez korzystania z dużego podejścia opartego na szablonie, takiego jak boost (bez obrazy, lubię boost!).
Autorem warstwy zgodności z systemem Windows jest Toni Ronkko. W Uniksie jest to standardowy nagłówek.
AKTUALIZACJA 2017 :
W C ++ 17 jest teraz oficjalnym sposób do plików wykazu systemu plików: std::filesystem. Poniżej znajduje się doskonała odpowiedź Shreevardhan z tego kodu źródłowego:
@ArtOfWarfare: tinydir nie został nawet utworzony, gdy udzielono odpowiedzi na to pytanie. Jest to również opakowanie wokół dirent (POSIX) i FindFirstFile (Windows), podczas gdy dirent.h po prostu otacza dirent dla Windows. Myślę, że to osobisty gust, ale dirent.h czuje się bardziej standardem
Peter Parker
7
@JoshC: ponieważ * ent jest tylko zwróconym wskaźnikiem wewnętrznej reprezentacji. przez zamknięcie katalogu wyeliminujesz również * ent. Ponieważ * ent jest tylko do czytania, myślę, że jest to rozsądny projekt.
Peter Parker
42
ludzie stają się prawdziwi !! to pytanie z 2009 roku i nawet nie wspomniało o VS. Więc nie krytykuj, że twoje pełne IDE (choć całkiem miłe) IDE nie obsługuje wielowiekowych standardów systemu operacyjnego. Również moja odpowiedź mówi, że jest ona „dostępna” dla systemu Windows, a nie „dołączona” w żadnym IDE od teraz i na zawsze ... Jestem prawie pewna, że możesz pobrać dirent i wstawić go do niektórych programów, takich jak dir i voila.
Peter Parker,
6
Odpowiedź jest myląca. Powinien zaczynać się od: „ ... używam dirent.h , dla którego istnieje również warstwa kompatybilności z otwartym oprogramowaniem Windows ”.
rustyx
10
W C ++ 14 jest std::experimental::filesystem, w C ++ 17 jest std::filesystem. Zobacz odpowiedź Shreevardhan poniżej. Więc nie ma potrzeby bibliotek zewnętrznych.
AFAIK może być również stosowany w C ++ 14, ale to wciąż eksperymentalna: namespace fs = std::experimental::filesystem;. Wygląda na to, że działa dobrze.
PeterK,
7
To powinna być preferowana odpowiedź dla bieżącego użycia (zaczynając od C ++ 17)
dioda zielona
4
Podczas przekazywania std::filesystem::pathdo std::coutcudzysłowu są uwzględniane w danych wyjściowych. Aby tego uniknąć, dołącz .string()do ścieżki, aby wykonać jawną zamiast niejawnej konwersji (tutaj std::cout << p.string() << std::endl;). Przykład: coliru.stacked-crooked.com/view?id=a55ea60bbd36a8a3
Roi Danton
2
Co ze znakami NIE-ASCII w nazwach plików? Nie std::wstringnależy używać lub jaki jest typ z iteratora?
anddero
2
Nie jestem pewien, czy jestem w tym sam, ale bez linkowania -lstdc++fs, dostałbym SIGSEGV (Address boundary error). Nigdzie w dokumentacji nie mogłem znaleźć, że jest to wymagane, a linker nie dał mi żadnej wskazówki. To działało zarówno dla, jak g++ 8.3.0i dla clang 8.0.0-3. Czy ktoś ma jakiś wgląd w to, gdzie takie rzeczy są określone w dokumentach / specyfikacjach?
swalog
229
Niestety standard C ++ nie definiuje standardowego sposobu pracy z plikami i folderami w ten sposób.
Ponieważ nie ma metody wieloplatformowej, najlepszym sposobem wieloplatformowym jest użycie biblioteki, takiej jak moduł systemu plików doładowania .
Metoda doładowania między platformami:
Poniższa funkcja, podając ścieżkę do katalogu i nazwę pliku, rekursywnie przeszukuje katalog i jego podkatalogi w poszukiwaniu nazwy pliku, zwracając wartość bool i, jeśli się powiedzie, ścieżkę do znalezionego pliku.
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))returnfalse;
directory_iterator end_itr;// default construction yields past-the-endfor(directory_iterator itr(dir_path); itr != end_itr;++itr){if(is_directory(itr->status())){if(find_file(itr->path(), file_name, path_found))returntrue;}elseif(itr->leaf()== file_name)// see below{
path_found = itr->path();returntrue;}}returnfalse;}
W C ++ 14 istnieje std::experimental::filesystem, w C ++ 17 istnieje std::filesystem, który ma podobną funkcjonalność jak boost (biblioteki lib pochodzą z boost). Zobacz odpowiedź Shreevardhan poniżej.
To rozwiązanie jest specyficzne dla platformy. Dlatego potrzebujesz bibliotek innych firm.
kraxor
9
@kraxor Tak, działa tylko w systemie Windows, ale OP nigdy nie prosi o rozwiązanie dla wielu platform. BTW, zawsze wolę wybierać coś bez korzystania z 3. bibliotek (jeśli to możliwe).
herohuyongtao
7
@herohuyongtao OP nigdy nie określił platformy, a podanie silnie zależnego od platformy rozwiązania ogólnego pytania może być mylące. (Co jeśli istnieje jedno-liniowe rozwiązanie, które działa tylko na PlayStation 3? Czy to dobra odpowiedź tutaj?) Widzę, że zredagowałeś swoją odpowiedź, aby stwierdzić, że działa ona tylko w systemie Windows, myślę, że w ten sposób jest w porządku.
kraxor
1
@herohuyongtao OP wspomniał, że nie może parsować ls, co oznacza, że prawdopodobnie jest na Uniksie. W każdym razie dobra odpowiedź dla Windows.
Thomas
2
Skończyło się na użyciu a, std::vector<std::wstring>a następnie fileName.c_str()zamiast wektora ciągów, których nie można skompilować.
PerryC,
51
Sprawdź tylko rozwiązanie typu C. Wymaga tylko dodatkowego nagłówka:
Bardzo miła sugestia. Nie przetestowałem go jeszcze na komputerze z systemem Windows, ale działa znakomicie w systemie OS X.
ArtOfWarfare
Biblioteka nie obsługuje std :: string, więc nie możesz przekazać file.c_str () do tinydir_open. W tym przypadku generuje błąd C2664 podczas kompilacji na msvc 2015.
Stepan Yakovenko
33
Polecam używać globz tym opakowaniem wielokrotnego użytku. Generuje vector<string>odpowiadające ścieżki plików, które pasują do wzorca globu:
Chciałbym użyć glob.h zgodnie z zaleceniami. Ale nadal nie mogę dołączyć pliku .h: Mówi No such file or directory. Czy możesz mi powiedzieć, jak rozwiązać ten problem?
Tofuw
Zauważ, że ta procedura przechodzi tylko jeden poziom w głąb (bez rekurencji). Nie sprawdza też szybko, czy jest to plik czy katalog, co można łatwo zrobić, przełączając GLOB_TILDEsię, GLOB_TILDE | GLOB_MARKa następnie sprawdzając ścieżki kończące się ukośnikiem. W razie potrzeby musisz wprowadzić dowolną modyfikację.
Volomike,
Czy to jest kompatybilne z wieloma platformami?
Nikhil Augustine
Niestety nie można znaleźć jednolicie ukrytych plików glob.
LmTinyToon,
23
Oto bardzo prosty kod przy C++11użyciu boost::filesystembiblioteki do uzyskiwania nazw plików w katalogu (z wyjątkiem nazw folderów):
#include<string>#include<iostream>#include<boost/filesystem.hpp>usingnamespace std;usingnamespace 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;}elsecontinue;}}
struct dirent {ino_t d_ino;/* inode number */off_t d_off;/* offset to the next dirent */unsignedshort d_reclen;/* length of this record */unsignedchar d_type;/* type of file */char d_name[256];/* filename */};
Chociaż ten link może odpowiedzieć na pytanie, lepiej dołączyć tutaj istotne części odpowiedzi i podać link w celach informacyjnych. Odpowiedzi zawierające tylko łącze mogą stać się nieprawidłowe, jeśli połączona strona ulegnie zmianie. - Z recenzji
ice1000
@ ice1000 Poważnie? Pytania i odpowiedzi pochodzą z 2009 r.
Tim
8
Sprawdź tę klasę, która korzysta z interfejsu API win32. Wystarczy skonstruować instancję, podając foldernameżądaną pozycję, a następnie wywołać getNextFilemetodę, aby uzyskać następną filenamez katalogu. Myślę, że potrzebuje windows.hi stdio.h.
classFileGetter{
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;}};
Czasami dobrze jest przejść od razu do źródła (zamierzona gra słów). Możesz się wiele nauczyć, patrząc na niektóre z najczęściej używanych poleceń w Linuksie. Założyłem proste zwierciadło podstawowych plików GNU na github (do czytania).
Jak mam to nazwać? Dostaję awarie, gdy próbuję uruchomić tę funkcję w pierwszym ifbloku. Nazywam to zchar **list; int numItems; exploreDirectory("/folder",list, numItems);
Hal T
2
To działa dla mnie. Przepraszam, jeśli nie pamiętam źródła. Prawdopodobnie pochodzi ze strony podręcznika man.
możesz pobrać wszystkie bezpośrednie pliki z katalogu głównego, używając std :: experimental :: filesystem :: directory_iterator (). Następnie przeczytaj nazwę tych ścieżek.
Ta odpowiedź powinna działać dla użytkowników systemu Windows, którzy mieli problemy z uzyskaniem pracy z Visual Studio z innymi odpowiedziami.
Pobierz plik dirent.h ze strony github. Ale lepiej jest po prostu użyć pliku Raw dirent.h i postępować zgodnie z poniższymi krokami (tak mam go uruchomić).
Umieść poniższą void filefinder()metodę w swoim kodzie i wywołaj ją z mainfunkcji lub edytuj funkcję, jak chcesz jej używać.
#include<stdio.h>#include<string.h>#include"dirent.h"string path ="C:/folder";//Put a valid path here for foldervoid 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);}
EDYCJA: Tę odpowiedź należy uznać za włamanie, ale naprawdę działa (choć w sposób specyficzny dla platformy), jeśli nie masz dostępu do bardziej eleganckich rozwiązań.
Nie wolno mi wykonywać polecenia „ls” i analizować wyników z mojego programu. Wiedziałem, że będzie ktoś, kto wyśle coś takiego ...
yyny
1
Ponieważ pliki i podkatalogi katalogu są zwykle przechowywane w strukturze drzewa, intuicyjnym sposobem jest użycie algorytmu DFS do rekurencyjnego przechodzenia między nimi. Oto przykład w systemie operacyjnym Windows przy użyciu podstawowych funkcji plików w io.h. Możesz zastąpić te funkcje na innej platformie. Chcę wyrazić, że podstawowa idea DFS doskonale spełnia ten problem.
#include<io.h>#include<iostream.h>#include<string>usingnamespace std;voidTraverseFilesUsingDFS(conststring& 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 dirif(handle ==-1){
cerr <<"folder path not exist: "<< folder_path << endl;exit(-1);}//iteratively check each file or sub_directory in current folderdo{string file_name=file_info.name;//from char array to string//check whtether it is a sub direcotry or a fileif(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);}
Próbowałem podążać za przykładem podanym w obu odpowiedziach i być może warto zauważyć, że wygląda na to, że std::filesystem::directory_entryzostał zmieniony tak, aby nie miał przeciążenia <<operatora. Zamiast tego std::cout << p << std::endl;musiałem użyć następujących, aby móc skompilować i uruchomić:
Jeśli wiesz, że będziesz używać tylko wielobajtów, których możesz użyć WIN32_FIND_DATAA, FindFirstFileAi FindNextFileA. Wtedy nie będzie potrzeby konwertowania wyniku na wielobajtowy lub danych wejściowych na Unicode.
Kiran Thilak,
0
Po prostu coś, czym chcę się podzielić i dziękuję za lekturę. Pobaw się z tą funkcją, aby ją trochę zrozumieć. Może ci się spodobać e oznacza rozszerzenie, p oznacza ścieżkę, a s oznacza separator ścieżki.
Jeśli ścieżka zostanie przekazana bez kończącego separatora, do ścieżki zostanie dołączony separator. W przypadku rozszerzenia, jeśli zostanie wprowadzony pusty ciąg, funkcja zwróci dowolny plik, który nie ma rozszerzenia w nazwie. Jeśli wprowadzono pojedynczą gwiazdkę, wszystkie pliki w katalogu zostaną zwrócone. Jeśli długość e jest większa niż 0, ale nie jest pojedynczą *, kropka zostanie dodana do e, jeśli e nie zawierało kropki w pozycji zerowej.
Dla wartości zwracanej. Jeśli zostanie zwrócona mapa o zerowej długości, nic nie zostanie znalezione, ale katalog jest otwarty. Jeśli indeks 999 jest dostępny z wartości zwracanej, ale rozmiar mapy wynosi tylko 1, oznacza to, że wystąpił problem z otwarciem ścieżki katalogu.
Należy pamiętać, że w celu zwiększenia wydajności funkcję tę można podzielić na 3 mniejsze funkcje. Ponadto możesz utworzyć funkcję wywołującą, która wykryje, którą funkcję wywoła na podstawie danych wejściowych. Dlaczego to jest bardziej wydajne? Powiedziane, jeśli masz zamiar pobrać wszystko, co jest plikiem, wykonując tę metodę podfunkcja zbudowana do pobierania wszystkich plików po prostu pobierze wszystkie pliki i nie będzie musiała oceniać żadnego innego niepotrzebnego warunku za każdym razem, gdy znajdzie plik.
Dotyczy to także pobierania plików, które nie mają rozszerzenia. Specjalna wbudowana funkcja do tego celu oceniałaby tylko pod kątem pogody, czy znaleziony obiekt jest plikiem, a następnie czy nazwa pliku zawiera kropkę.
Oszczędność może nie być duża, jeśli czytasz tylko katalogi z mniejszą ilością plików. Ale jeśli czytasz dużą liczbę katalogów lub jeśli katalog zawiera kilkaset tysięcy plików, może to być ogromna oszczędność.
#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 ="",unsignedchar 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(constauto&p : m){
std::cout <<"m["<< p.first <<"] = "<< p.second << std::endl;}}int main(){
std::map<int, std::string> k = getFile("./","");
printMap(k);return0;}
To zadziałało dla mnie. Zapisuje plik zawierający tylko nazwy (bez ścieżki) wszystkich plików. Następnie odczytuje ten plik txt i drukuje go dla ciebie.
stat()
błąd „brak takiego pliku lub katalogu”, gdy nazwa pliku jest zwracana przezreaddir()
.Odpowiedzi:
W małych i prostych zadaniach nie używam doładowania, używam dirent.h, który jest również dostępny dla systemu Windows:
Jest to tylko mały plik nagłówkowy i wykonuje większość prostych czynności, których potrzebujesz, bez korzystania z dużego podejścia opartego na szablonie, takiego jak boost (bez obrazy, lubię boost!).
Autorem warstwy zgodności z systemem Windows jest Toni Ronkko. W Uniksie jest to standardowy nagłówek.
AKTUALIZACJA 2017 :
W C ++ 17 jest teraz oficjalnym sposób do plików wykazu systemu plików:
std::filesystem
. Poniżej znajduje się doskonała odpowiedź Shreevardhan z tego kodu źródłowego:źródło
std::experimental::filesystem
, w C ++ 17 jeststd::filesystem
. Zobacz odpowiedź Shreevardhan poniżej. Więc nie ma potrzeby bibliotek zewnętrznych.C ++ 17 ma teraz
std::filesystem::directory_iterator
, którego można używać jakoPonadto,
std::filesystem::recursive_directory_iterator
można iteracyjne podkatalogi również.źródło
namespace fs = std::experimental::filesystem;
. Wygląda na to, że działa dobrze.std::filesystem::path
dostd::cout
cudzysłowu są uwzględniane w danych wyjściowych. Aby tego uniknąć, dołącz.string()
do ścieżki, aby wykonać jawną zamiast niejawnej konwersji (tutajstd::cout << p.string() << std::endl;
). Przykład: coliru.stacked-crooked.com/view?id=a55ea60bbd36a8a3std::wstring
należy używać lub jaki jest typ z iteratora?-lstdc++fs
, dostałbymSIGSEGV (Address boundary error)
. Nigdzie w dokumentacji nie mogłem znaleźć, że jest to wymagane, a linker nie dał mi żadnej wskazówki. To działało zarówno dla, jakg++ 8.3.0
i dlaclang 8.0.0-3
. Czy ktoś ma jakiś wgląd w to, gdzie takie rzeczy są określone w dokumentach / specyfikacjach?Niestety standard C ++ nie definiuje standardowego sposobu pracy z plikami i folderami w ten sposób.
Ponieważ nie ma metody wieloplatformowej, najlepszym sposobem wieloplatformowym jest użycie biblioteki, takiej jak moduł systemu plików doładowania .
Metoda doładowania między platformami:
Źródło ze strony doładowania wspomnianej powyżej.
W systemach opartych na Unix / Linux:
Możesz użyć opendir / readdir / closedir .
Kod źródłowy z powyższych stron podręcznika.
W przypadku systemów opartych na systemie Windows:
Możesz użyć funkcji Win32 API FindFirstFile / FindNextFile / FindClose .
Kod źródłowy z powyższych stron msdn.
źródło
FindFirstFile(TEXT("D:\\IMAGE\\MYDIRECTORY\\*"), &findFileData);
std::experimental::filesystem
, w C ++ 17 istniejestd::filesystem
, który ma podobną funkcjonalność jak boost (biblioteki lib pochodzą z boost). Zobacz odpowiedź Shreevardhan poniżej.Wystarczy jedna funkcja, nie musisz używać żadnej biblioteki innej firmy (dla systemu Windows).
PS: jak wspomniano w @Sebastian, możesz zmienić
*.*
na*.ext
, aby uzyskać tylko pliki EXT (tj. Określonego typu) w tym katalogu.źródło
std::vector<std::wstring>
a następniefileName.c_str()
zamiast wektora ciągów, których nie można skompilować.Sprawdź tylko rozwiązanie typu C. Wymaga tylko dodatkowego nagłówka:
https://github.com/cxong/tinydir
Niektóre zalety w stosunku do innych opcji:
readdir_r
tam, gdzie jest dostępny, co oznacza, że jest (zwykle) bezpieczny dla wątkówUNICODE
makrźródło
Polecam używać
glob
z tym opakowaniem wielokrotnego użytku. Generujevector<string>
odpowiadające ścieżki plików, które pasują do wzorca globu:Które można następnie wywołać za pomocą normalnego systemu symboli wieloznacznych, takiego jak:
źródło
No such file or directory
. Czy możesz mi powiedzieć, jak rozwiązać ten problem?GLOB_TILDE
się,GLOB_TILDE | GLOB_MARK
a następnie sprawdzając ścieżki kończące się ukośnikiem. W razie potrzeby musisz wprowadzić dowolną modyfikację.glob
.Oto bardzo prosty kod przy
C++11
użyciuboost::filesystem
biblioteki do uzyskiwania nazw plików w katalogu (z wyjątkiem nazw folderów):Wyjście jest jak:
źródło
boost::filesystem
biblioteki boost.org/doc/libs/1_58_0/libs/filesystem/doc/index.htmDlaczego nie użyć
glob()
?źródło
Myślę, że poniżej fragmentu można użyć do wyświetlenia wszystkich plików.
Poniżej znajduje się struktura struktury dirent
źródło
Wypróbuj boost dla metody X-platform
http://www.boost.org/doc/libs/1_38_0/libs/filesystem/doc/index.htm
lub po prostu użyj plików specyficznych dla systemu operacyjnego.
źródło
Sprawdź tę klasę, która korzysta z interfejsu API win32. Wystarczy skonstruować instancję, podając
foldername
żądaną pozycję, a następnie wywołaćgetNextFile
metodę, aby uzyskać następnąfilename
z katalogu. Myślę, że potrzebujewindows.h
istdio.h
.źródło
Podręcznik GNU FTW
http://www.gnu.org/software/libc/manual/html_node/Simple-Directory-Lister.html#Simple-Directory-Lister
Czasami dobrze jest przejść od razu do źródła (zamierzona gra słów). Możesz się wiele nauczyć, patrząc na niektóre z najczęściej używanych poleceń w Linuksie. Założyłem proste zwierciadło podstawowych plików GNU na github (do czytania).
https://github.com/homer6/gnu_coreutils/blob/master/src/ls.c
Być może nie dotyczy to systemu Windows, ale przy użyciu tych metod można mieć wiele przypadków użycia wariantów uniksowych.
Mam nadzieję, że pomoże ...
źródło
Odpowiedź Shreevardhan działa świetnie. Ale jeśli chcesz go użyć w c ++ 14, po prostu dokonaj zmiany
namespace fs = experimental::filesystem;
to znaczy,
źródło
źródło
Mam nadzieję, że ten kod ci pomoże.
źródło
string2wchar_t
zwraca adres zmiennej lokalnej. Powinieneś także prawdopodobnie użyć metod konwersji dostępnych w WinAPI zamiast pisać własne.Ta implementacja realizuje Twój cel, dynamicznie wypełniając tablicę ciągów treścią określonego katalogu.
źródło
if
bloku. Nazywam to zchar **list; int numItems; exploreDirectory("/folder",list, numItems);
To działa dla mnie. Przepraszam, jeśli nie pamiętam źródła. Prawdopodobnie pochodzi ze strony podręcznika man.
źródło
możesz pobrać wszystkie bezpośrednie pliki z katalogu głównego, używając std :: experimental :: filesystem :: directory_iterator (). Następnie przeczytaj nazwę tych ścieżek.
źródło
Ta odpowiedź powinna działać dla użytkowników systemu Windows, którzy mieli problemy z uzyskaniem pracy z Visual Studio z innymi odpowiedziami.
Pobierz plik dirent.h ze strony github. Ale lepiej jest po prostu użyć pliku Raw dirent.h i postępować zgodnie z poniższymi krokami (tak mam go uruchomić).
Strona Github dla dirent.h dla Windows: Strona Github dla dirent.h
Plik Raw Dirent : Plik Raw dirent.h
Przejdź do swojego projektu i dodaj nowy przedmiot ( Ctrl+ Shift+ A). Dodaj plik nagłówka (.h) i nazwij go dirent.h.
Wklej kod pliku Raw dirent.h do nagłówka.
Dołącz „dirent.h” do swojego kodu.
Umieść poniższą
void filefinder()
metodę w swoim kodzie i wywołaj ją zmain
funkcji lub edytuj funkcję, jak chcesz jej używać.źródło
System nazwij to!
Następnie po prostu przeczytaj plik.
EDYCJA: Tę odpowiedź należy uznać za włamanie, ale naprawdę działa (choć w sposób specyficzny dla platformy), jeśli nie masz dostępu do bardziej eleganckich rozwiązań.
źródło
Ponieważ pliki i podkatalogi katalogu są zwykle przechowywane w strukturze drzewa, intuicyjnym sposobem jest użycie algorytmu DFS do rekurencyjnego przechodzenia między nimi. Oto przykład w systemie operacyjnym Windows przy użyciu podstawowych funkcji plików w io.h. Możesz zastąpić te funkcje na innej platformie. Chcę wyrazić, że podstawowa idea DFS doskonale spełnia ten problem.
źródło
Próbowałem podążać za przykładem podanym w obu odpowiedziach i być może warto zauważyć, że wygląda na to, że
std::filesystem::directory_entry
został zmieniony tak, aby nie miał przeciążenia<<
operatora. Zamiast tegostd::cout << p << std::endl;
musiałem użyć następujących, aby móc skompilować i uruchomić:próba przejścia
p
sama,std::cout <<
powodując błąd braku przeładowania.źródło
Opierając się na tym, co opublikował herohuyongtao i kilka innych postów:
http://www.cplusplus.com/forum/general/39766/
Jaki jest oczekiwany typ danych wejściowych FindFirstFile?
Jak przekonwertować ciąg na ciąg?
To jest rozwiązanie dla systemu Windows.
Ponieważ chciałem przekazać std :: string i zwrócić wektor ciągów, musiałem dokonać kilku konwersji.
źródło
WIN32_FIND_DATAA
,FindFirstFileA
iFindNextFileA
. Wtedy nie będzie potrzeby konwertowania wyniku na wielobajtowy lub danych wejściowych na Unicode.Po prostu coś, czym chcę się podzielić i dziękuję za lekturę. Pobaw się z tą funkcją, aby ją trochę zrozumieć. Może ci się spodobać e oznacza rozszerzenie, p oznacza ścieżkę, a s oznacza separator ścieżki.
Jeśli ścieżka zostanie przekazana bez kończącego separatora, do ścieżki zostanie dołączony separator. W przypadku rozszerzenia, jeśli zostanie wprowadzony pusty ciąg, funkcja zwróci dowolny plik, który nie ma rozszerzenia w nazwie. Jeśli wprowadzono pojedynczą gwiazdkę, wszystkie pliki w katalogu zostaną zwrócone. Jeśli długość e jest większa niż 0, ale nie jest pojedynczą *, kropka zostanie dodana do e, jeśli e nie zawierało kropki w pozycji zerowej.
Dla wartości zwracanej. Jeśli zostanie zwrócona mapa o zerowej długości, nic nie zostanie znalezione, ale katalog jest otwarty. Jeśli indeks 999 jest dostępny z wartości zwracanej, ale rozmiar mapy wynosi tylko 1, oznacza to, że wystąpił problem z otwarciem ścieżki katalogu.
Należy pamiętać, że w celu zwiększenia wydajności funkcję tę można podzielić na 3 mniejsze funkcje. Ponadto możesz utworzyć funkcję wywołującą, która wykryje, którą funkcję wywoła na podstawie danych wejściowych. Dlaczego to jest bardziej wydajne? Powiedziane, jeśli masz zamiar pobrać wszystko, co jest plikiem, wykonując tę metodę podfunkcja zbudowana do pobierania wszystkich plików po prostu pobierze wszystkie pliki i nie będzie musiała oceniać żadnego innego niepotrzebnego warunku za każdym razem, gdy znajdzie plik.
Dotyczy to także pobierania plików, które nie mają rozszerzenia. Specjalna wbudowana funkcja do tego celu oceniałaby tylko pod kątem pogody, czy znaleziony obiekt jest plikiem, a następnie czy nazwa pliku zawiera kropkę.
Oszczędność może nie być duża, jeśli czytasz tylko katalogi z mniejszą ilością plików. Ale jeśli czytasz dużą liczbę katalogów lub jeśli katalog zawiera kilkaset tysięcy plików, może to być ogromna oszczędność.
źródło
źródło
To zadziałało dla mnie. Zapisuje plik zawierający tylko nazwy (bez ścieżki) wszystkich plików. Następnie odczytuje ten plik txt i drukuje go dla ciebie.
źródło