Przeszukiwanie ścieżki w poszukiwaniu plików za pomocą funkcji _findfirst i _findnext
Stronę tą wyświetlono już: 4418 razy
Pobawiliśmy się już w zapisywanie i odczytywanie danych z i do pliku, teraz kolej przyszła pobuszować w katalogach i nauczyć się znajdowania plików i folderów zawartych w danej lokalizacji. Do tego celu można posłużyć się funkcjami _findfirst oraz _findnext, które umożliwiają przeszukiwanie danej ścieżki według podanego filtra przeszukiwania. Oto przykłady filtrów, wraz z ich opisem:
- C:\* - wyszukiwanie wszystkich elementów zawartych w podanej lokalizacji;
- C:\*.txt - wyszuka wszystkie pliki z rozszerzeniem txt;
- C:\?1*.txt - wyszuka wszystkie pliki, które po pierwszym dowolnym znaku mają 1 w nazwie a za nią dowolną liczbę innych znaków i kończą się rozszerzeniem .txt (przykłady: "f1000.txt"; "11.txt" ...)
Oto przykładowy mały programik przeszukujący daną lokalizację oraz podfoldery i wyświetlająca katalogi i nazwy plików, w których dany plik został znaleziony:
- #include <iostream>
- #include <vector>
- #include <string>
- #include <windows.h>
- #include <io.h>
- using namespace std;
- void searchFile(string path, string filtr){
- _finddata_t f;
- intptr_t r;
- // przeszukiwanie podfolderów
- string searching_filtr = path; // tworzę filtr przeszukiwania folderów
- searching_filtr += "*"; // na końcu potrzebna jest *
- if((r=_findfirst(searching_filtr.c_str(),&f))>0){ // znajdowanie pierwszego folderu (to zawsze jest .
- while(!_findnext(r,&f)){
- if(strcmp(f.name, "..")){ // drugi to ..
- if(f.attrib & _A_SUBDIR){ // gdy dany element jest folderem to
- string p2 = path; // kopię ścieżki głównej robię
- p2 += f.name; // dodaję do tego nazwę folderu
- p2 += char(92); // dodaję na końcu
- searchFile(p2, filtr); // przeszukuję nową lokalizację
- }
- }
- }
- }
- _findclose(r); // zamykam przeszukiwanie
- // wyszukiwanie plików według podanego filtra
- searching_filtr = path; // tworzę ścieżkę dla filtra
- searching_filtr += filtr; // dodaję na koniec filtr
- if((r=_findfirst(searching_filtr.c_str(),&f))>0){ // piersze przeszukiwanie
- do{ // kolejne przeszukiwania
- if(!(f.attrib & _A_SUBDIR)){ // jak nie jest to folder
- cout<<path<<"t"<<f.name<<endl; // wypisuję nazwę znalezionego pliku
- }
- }while(!_findnext(r,&f));
- }
- _findclose(r); // zamykam przeszukiwanie
- }
- int main(int size, char** pt){
- setlocale(LC_CTYPE,"Polish"); // polskie znaki
- string path = pt[0]; // wyciągam ścieżkę z nazwą programu
- string filtr = "*.*"; // to będzie filtr przeszukiwania
- path.erase(path.begin() + path.find_last_of(char(92),string::npos) + 1,path.end()); // wydziabuję ścieżkę dostępu do lokalizacji programu
- cout<<"Przeszukiwanie ścieżki: \""<<path<<"\" z filtrem wyszukiwania \""<<filtr<<"\""<<endl<<endl; // wyświetlam
- searchFile(path,filtr);
- cout<<endl<<endl<<"Wciśnij enter, aby zamknąć program...";
- cin.get();
- return 0;
- }
Warto przyjrzeć się nieco dokładniej strukturze _finddata_t, która ma następującą postać:
- struct _finddata64i32_t {
- unsigned attrib; // atrybuty pliku
- __time64_t time_create; // czas utworzenia pliku
- __time64_t time_access; // czas ostatniego dostępu do pliku
- __time64_t time_write; // czas ostatniego nadpisania pliku
- _fsize_t size; // rozmiar pliku
- char name[260]; // nazwa pliku (maksymalnie 259 znaków bo jeden jest przeznaczony na NULL)
- };
- typedef _finddata64i32_t _finddata_t;
W zależności od systemu może stosowane są nieco inne deklaracje tej samej struktury, stąd też zapis na końcu typedef _finddata64i32_t _finddata_t;.
Warto przyjrzeć się polu struktury attrib, dla którego ustawienia bitów mówią o rodzaju i dostępie do danego pliku:
- #define _A_NORMAL 0x00 // normalny plik - bez zakazu odczytu/zapisu
- #define _A_RDONLY 0x01 // tylko do odczytu
- #define _A_HIDDEN 0x02 // ukryty
- #define _A_SYSTEM 0x04 // systemowy
- #define _A_SUBDIR 0x10 // podfolder
- #define _A_ARCH 0x20 // archiwalny
Ponieważ dany typ pliku czy folderu może mieć kilka różnych atrybutów, konieczne jest wykorzystanie operatora koniunkcji bitowej & (czyli AND). Dla folderów taki test będzie wyglądał następująco:
- if(f.attrib & _A_SUBDIR){
- cout<<"To jest folder!!!"<<endl;
- }
Powyższe sprawdzenie zostało już oczywiście wykorzystane w programie.
![]() | Funkcje _findfirst i _findnext są nieco przestarzałe i nie obsługują szerokich znaków (typ wchar_t), co w konsekwencji może doprowadzić, że plik zawierający w nazwie znaki kodowania np. cyrylicy czy alfabetu greckiego nie będą poprawnie obsługiwane. Z tego względu warto też zwrócić uwagę na funkcje _wfindfirst oraz _wfindnext. |

Tytuł:
Architektura oprogramowania bez tajemnic. Wykorzystaj język C++ do tworzenia wydajnych aplikacji i systemów
Autor:
Adrian Ostrowski, Piotr Gaczkowski

Tytuł:
Opus magnum C++ 11. Programowanie w języku C++. Wydanie II poprawione (komplet)
Autor:
Jerzy Grębosz

Tytuł:
Programowanie wieloplatformowe z C++ i wxWidgets 3
Autor:
Bartosz W. Warzocha

Tytuł:
Język C++ i przetwarzanie współbieżne w akcji. Wydanie II
Autor:
Anthony Williams

Tytuł:
C++ dla bystrzaków. Wydanie VII
Autor:
Stephen R. Davis

Tytuł:
Tablice informatyczne. Podstawy C++
Autor:
Radosław Sokół

Tytuł:
Opus magnum C++11. Programowanie w języku C++ (komplet)
Autor:
Jerzy Grębosz

Tytuł:
OpenCV 3. Komputerowe rozpoznawanie obrazu w C++ przy użyciu biblioteki OpenCV
Autor:
Adrian Kaehler, Gary Bradski

Tytuł:
C++ w 24 godziny. Wydanie VI
Autor:
Rogers Cadenhead, Jesse Liberty

Tytuł:
C++ Optymalizacja kodu. Sprawdzone techniki zwiększania wydajności
Autor:
Guntheroth Kurt