@ Chish - Ya tapi yang ini memiliki klasik "Saya tidak diizinkan mengeksekusi 'ls'"! Ini persis bagaimana saya akan merasa tahun 1 Ilmu Komputer. ; D <3 x
James Bedford
1
C dan C ++ bukan bahasa yang sama. Oleh karena itu, prosedur untuk menyelesaikan tugas ini akan berbeda dalam kedua bahasa. Silakan pilih satu dan beri tag ulang sesuai.
MD XF
2
Dan tak satu pun dari bahasa tersebut (selain C ++ sejak C ++ 17) bahkan memiliki konsep direktori - jadi jawaban apa pun kemungkinan bergantung pada OS Anda, atau pada pustaka abstraksi apa pun yang mungkin Anda gunakan.
Toby Speight
Jawaban:
809
Dalam tugas-tugas kecil dan sederhana saya tidak menggunakan boost, saya menggunakan dirent.h yang juga tersedia untuk 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;}
Ini hanya file header kecil dan melakukan sebagian besar hal-hal sederhana yang Anda butuhkan tanpa menggunakan pendekatan berbasis template besar seperti boost (jangan tersinggung, saya suka boost!).
Penulis lapisan kompatibilitas windows adalah Toni Ronkko. Di Unix, itu adalah header standar.
PEMBARUAN 2017 :
Dalam C ++ 17 sekarang ada cara resmi untuk daftar file dari sistem file Anda: std::filesystem. Ada jawaban yang sangat baik dari Shreevardhan di bawah ini dengan kode sumber ini:
@ArtOfWarfare: tinydir bahkan tidak dibuat ketika pertanyaan ini dijawab. Juga itu adalah pembungkus di sekitar dirent (POSIX) dan FindFirstFile (Windows), sementara dirent.h hanya membungkus dirent untuk windows. Saya pikir itu adalah selera pribadi, tetapi dirent.h terasa lebih sebagai standar
Peter Parker
7
@JoshC: karena * ent hanyalah pointer yang dikembalikan dari representasi internal. dengan menutup direktori Anda akan menghilangkan * ent juga. Karena * ent hanya untuk membaca, saya rasa ini adalah desain yang waras.
Peter Parker
42
orang jadi nyata !! ini adalah pertanyaan dari tahun 2009 dan bahkan belum disebutkan VS. Jadi jangan mengkritik bahwa IDE milik Anda (walaupun cukup bagus) tidak mendukung standar OS lama. Juga jawaban saya mengatakan itu "tersedia" untuk windows, tidak "termasuk" dalam IDE apa pun dari sekarang dan setiap saat ... Saya cukup yakin Anda dapat mengunduh dirent dan memasukkannya ke dalam beberapa direktori termasuk dir dan voila itu ada.
Peter Parker
6
Jawabannya menyesatkan. Itu harus dimulai dengan: " ... Saya menggunakan dirent.h , di mana lapisan kompatibilitas open-source Windows juga ada ".
rustyx
10
Dengan C ++ 14 ada std::experimental::filesystem, dengan C ++ 17 ada std::filesystem. Lihat jawaban Shreevardhan di bawah ini. Jadi tidak perlu untuk perpustakaan pihak ke-3.
AFAIK juga dapat digunakan dalam C ++ 14, tapi ada masih eksperimental: namespace fs = std::experimental::filesystem;. Tampaknya berfungsi ok.
PeterK
7
Ini harus menjadi jawaban yang lebih disukai untuk penggunaan saat ini (dimulai dengan C ++ 17)
green diod
4
Mengindahkan ketika melewati std::filesystem::pathke std::cout, tanda kutip termasuk dalam output. Untuk menghindarinya, tambahkan .string()jalur untuk melakukan konversi eksplisit dan bukan implisit (di sini std::cout << p.string() << std::endl;). Contoh: coliru.stacked-crooked.com/view?id=a55ea60bbd36a8a3
Roi Danton
2
Bagaimana dengan karakter NON-ASCII dalam nama file? Tidak std::wstringboleh digunakan atau apa jenis dari iterator?
anddero
2
Saya tidak yakin apakah saya sendirian dalam hal ini, tetapi tanpa menghubungkan ke -lstdc++fs, saya akan mendapatkan SIGSEGV (Address boundary error). Saya tidak dapat menemukan di mana pun dalam dokumentasi bahwa ini diperlukan, dan tautan tidak memberikan petunjuk apa pun. Ini bekerja untuk keduanya g++ 8.3.0dan clang 8.0.0-3. Apakah ada yang punya wawasan ke mana hal-hal seperti ini ditentukan dalam dokumen / spesifikasi?
swalog
229
Sayangnya standar C ++ tidak mendefinisikan cara standar untuk bekerja dengan file dan folder dengan cara ini.
Karena tidak ada cara lintas platform, cara lintas platform terbaik adalah dengan menggunakan perpustakaan seperti modul sistem file boost .
Metode peningkatan lintas platform:
Fungsi berikut, diberi jalur direktori dan nama file, secara rekursif mencari direktori dan sub-direktori untuk nama file, mengembalikan bool, dan jika berhasil, path ke file yang ditemukan.
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;}
Sumber dari halaman boost yang disebutkan di atas.
Dengan C ++ 14 ada std::experimental::filesystem, dengan C ++ 17 ada std::filesystem, yang memiliki fungsi yang sama dengan boost (libs berasal dari boost). Lihat jawaban Shreevardhan di bawah ini.
Satu fungsi sudah cukup, Anda tidak perlu menggunakan perpustakaan pihak ke-3 (untuk Windows).
#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: seperti yang disebutkan oleh @Sebastian, Anda bisa mengubah *.*ke *.extuntuk mendapatkan hanya file EXT (yaitu dari jenis tertentu) di direktori itu.
Solusi ini jika spesifik platform. Itulah alasan Anda membutuhkan perpustakaan pihak ketiga.
kraxor
9
@ kraxor Ya, itu hanya bekerja di Windows, tetapi OP tidak pernah meminta untuk memiliki solusi lintas platform. BTW, saya selalu memilih untuk memilih sesuatu tanpa menggunakan perpustakaan ke-3 (jika mungkin).
herohuyongtao
7
@herohuyongtao OP tidak pernah menentukan platform, dan memberikan solusi yang sangat tergantung platform untuk pertanyaan umum bisa menyesatkan. (Bagaimana jika ada solusi satu baris yang hanya berfungsi di PlayStation 3? Apakah itu jawaban yang bagus di sini?) Saya melihat Anda mengedit jawaban Anda untuk menyatakan bahwa itu hanya berfungsi pada Windows, saya kira tidak apa-apa dengan cara ini.
kraxor
1
@herohuyongtao OP menyebutkan dia tidak dapat menguraikan ls, artinya dia mungkin menggunakan unix .. bagaimanapun, jawaban yang bagus untuk Windows.
Thomas
2
Saya akhirnya menggunakan std::vector<std::wstring>dan fileName.c_str()bukannya vektor string, yang tidak akan dikompilasi.
PerryC
51
Untuk solusi C saja, silakan periksa ini. Hanya membutuhkan tajuk tambahan:
Saran yang sangat bagus. Saya belum mengujinya di komputer windows tetapi ia bekerja dengan sangat baik pada OS X.
ArtOfWarfare
Perpustakaan tidak mendukung std :: string, jadi Anda tidak dapat meneruskan file.c_str () ke tinydir_open. Ini memberikan kesalahan C2664 selama kompilasi pada msvc 2015 dalam hal ini.
Stepan Yakovenko
33
Saya sarankan menggunakan globpembungkus yang dapat digunakan kembali ini. Ini menghasilkan yang vector<string>sesuai dengan jalur file yang sesuai dengan pola glob:
Saya ingin menggunakan glob.h seperti yang Anda rekomendasikan. Tapi tetap saja, saya tidak bisa memasukkan file .h: Dikatakan No such file or directory. Bisakah Anda memberi tahu saya cara mengatasi masalah ini?
Tofuw
Perhatikan bahwa rutin ini hanya memiliki kedalaman satu tingkat (tanpa rekursi). Itu juga tidak melakukan pemeriksaan cepat untuk menentukan apakah itu file atau direktori, yang dapat Anda lakukan dengan mudah dengan beralih GLOB_TILDEdengan GLOB_TILDE | GLOB_MARKdan kemudian memeriksa jalur yang berakhir dengan garis miring. Anda harus membuat modifikasi untuk itu jika Anda membutuhkannya.
Volomike
Apakah cross-platform ini kompatibel?
Nikhil Augustine
Sayangnya Anda tidak dapat menemukan file yang disembunyikan secara seragam melalui glob.
LmTinyToon
23
Berikut ini adalah kode yang sangat sederhana dalam C++11menggunakan boost::filesystemperpustakaan untuk mendapatkan nama file dalam direktori (tidak termasuk nama folder):
#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 */};
Meskipun tautan ini dapat menjawab pertanyaan, lebih baik untuk memasukkan bagian-bagian penting dari jawaban di sini dan memberikan tautan untuk referensi. Jawaban hanya tautan dapat menjadi tidak valid jika halaman tertaut berubah. - Dari Ulasan
ice1000
@ ice1000 Serius? T&J ini dari 2009
Tim
8
Lihat kelas ini yang menggunakan api win32. Cukup buat instance dengan menyediakan foldernamedari mana Anda ingin listing kemudian panggil getNextFilemetode untuk mendapatkan yang berikutnya filenamedari direktori. Saya pikir itu perlu windows.hdan 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;}};
Juga, kadang-kadang ada baiknya langsung ke sumbernya (pun intended). Anda dapat belajar banyak dengan melihat jeroan dari beberapa perintah yang paling umum di Linux. Saya telah membuat mirror sederhana dari GNU's coreutils di github (untuk membaca).
Jawaban Shreevardhan bekerja dengan sangat baik. Tetapi jika Anda ingin menggunakannya di c ++ 14, lakukan saja perubahannamespace fs = experimental::filesystem;
yaitu,
#include<string>#include<iostream>#include<filesystem>usingnamespace 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;}
-1. string2wchar_tmengembalikan alamat variabel lokal. Juga, Anda mungkin harus menggunakan metode konversi yang tersedia di WinAPI alih-alih menulis metode Anda sendiri.
Daniel Kamil Kozar
3
Implementasi ini mewujudkan tujuan Anda, secara dinamis mengisi serangkaian string dengan konten direktori yang ditentukan.
int exploreDirectory(constchar*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);return0;}
Bagaimana saya menyebutnya? Saya mendapatkan segfault ketika saya mencoba menjalankan fungsi ini di ifblok pertama . Saya menyebutnya denganchar **list; int numItems; exploreDirectory("/folder",list, numItems);
Hal T
2
Ini bekerja untuk saya. Maaf jika saya tidak dapat mengingat sumbernya. Mungkin dari halaman manual.
Anda bisa mendapatkan semua file langsung di direktori root Anda dengan menggunakan std :: experimental :: filesystem :: directory_iterator (). Kemudian, baca nama pathfiles ini.
Jawaban ini seharusnya berfungsi untuk pengguna Windows yang mengalami kesulitan dalam menjalankan ini dengan Visual Studio dengan jawaban lain mana pun.
Unduh file dirent.h dari halaman github. Tetapi lebih baik hanya menggunakan file Raw dirent.h dan ikuti langkah-langkah saya di bawah ini (ini adalah cara saya membuatnya bekerja).
Masukkan void filefinder()metode di bawah ini dalam kode Anda dan panggil dari mainfungsi Anda atau edit fungsi bagaimana Anda ingin menggunakannya.
#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);}
EDIT: Jawaban ini harus dianggap sebagai peretasan, tetapi ini benar-benar berfungsi (walaupun dengan cara khusus platform) jika Anda tidak memiliki akses ke solusi yang lebih elegan.
Saya tidak diizinkan untuk menjalankan perintah 'ls' dan menguraikan hasil dari dalam program saya. Saya tahu akan ada seseorang yang akan mengirim sesuatu seperti ini ...
yyny
1
Karena file dan sub direktori direktori umumnya disimpan dalam struktur pohon, cara intuitif adalah dengan menggunakan algoritma DFS untuk secara rekursif melintasi masing-masing. Berikut adalah contoh dalam sistem operasi windows dengan menggunakan fungsi file dasar di io.h. Anda dapat mengganti fungsi-fungsi ini di platform lain. Yang ingin saya ungkapkan adalah bahwa ide dasar DFS memenuhi masalah ini dengan sempurna.
#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);}
Saya mencoba mengikuti contoh yang diberikan di kedua jawaban dan mungkin perlu dicatat bahwa tampaknya seolah-olah std::filesystem::directory_entrytelah diubah untuk tidak memiliki kelebihan <<operator. Alih-alih std::cout << p << std::endl;saya harus menggunakan yang berikut ini untuk dapat mengkompilasi dan membuatnya berfungsi:
Jika Anda tahu bahwa Anda hanya akan menggunakan multibyte, Anda dapat menggunakan WIN32_FIND_DATAA, FindFirstFileAdan FindNextFileA. Maka Tidak perlu mengubah hasil menjadi multibyte atau Input ke unicode.
Kiran Thilak
0
Hanya sesuatu yang ingin saya bagikan dan terima kasih atas bahan bacaannya. Bermain-main dengan fungsi untuk sedikit memahaminya. Anda mungkin menyukainya. e berdiri untuk ekstensi, p adalah untuk path, dan s adalah untuk path separator.
Jika jalur dilewatkan tanpa mengakhiri pemisah, pemisah akan ditambahkan ke jalur. Untuk ekstensi, jika string kosong dimasukkan maka fungsi akan mengembalikan file apa pun yang tidak memiliki ekstensi dalam namanya. Jika satu bintang dimasukkan dari semua file dalam direktori akan dikembalikan. Jika panjang e lebih besar dari 0 tetapi bukan satu * maka titik akan ditambahkan ke e jika e tidak mengandung titik di posisi nol.
Untuk nilai kembali. Jika peta nol panjang dikembalikan maka tidak ada yang ditemukan tetapi direktori terbuka oke. Jika indeks 999 tersedia dari nilai kembali tetapi ukuran peta hanya 1 maka itu berarti ada masalah dengan membuka jalur direktori.
Perhatikan bahwa untuk efisiensi, fungsi ini dapat dibagi menjadi 3 fungsi yang lebih kecil. Selain itu, Anda dapat membuat fungsi pemanggil yang akan mendeteksi fungsi mana yang akan dipanggil berdasarkan input. Mengapa itu lebih efisien? Mengatakan jika Anda akan mengambil semua yang merupakan file, melakukan metode itu subfungsi yang dibangun untuk mengambil semua file hanya akan mengambil semua file dan tidak perlu mengevaluasi kondisi lain yang tidak perlu setiap kali ditemukan file.
Itu juga berlaku ketika Anda mengambil file yang tidak memiliki ekstensi. Fungsi dibangun khusus untuk tujuan itu hanya akan mengevaluasi cuaca jika objek yang ditemukan adalah file dan kemudian apakah nama file memiliki titik di dalamnya.
Penghematan mungkin tidak banyak jika Anda hanya membaca direktori dengan tidak banyak file. Tetapi jika Anda membaca sejumlah besar direktori atau jika direktori tersebut memiliki beberapa ratus ribu file, ini bisa menjadi penghematan besar.
#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;}
Ini berhasil untuk saya. Itu menulis file dengan hanya nama (tidak ada jalur) dari semua file. Kemudian ia membaca file txt itu dan mencetaknya untuk Anda.
stat()
kesalahan 'tidak ada file atau direktori' ketika nama file dikembalikan olehreaddir()
.Jawaban:
Dalam tugas-tugas kecil dan sederhana saya tidak menggunakan boost, saya menggunakan dirent.h yang juga tersedia untuk windows:
Ini hanya file header kecil dan melakukan sebagian besar hal-hal sederhana yang Anda butuhkan tanpa menggunakan pendekatan berbasis template besar seperti boost (jangan tersinggung, saya suka boost!).
Penulis lapisan kompatibilitas windows adalah Toni Ronkko. Di Unix, itu adalah header standar.
PEMBARUAN 2017 :
Dalam C ++ 17 sekarang ada cara resmi untuk daftar file dari sistem file Anda:
std::filesystem
. Ada jawaban yang sangat baik dari Shreevardhan di bawah ini dengan kode sumber ini:sumber
std::experimental::filesystem
, dengan C ++ 17 adastd::filesystem
. Lihat jawaban Shreevardhan di bawah ini. Jadi tidak perlu untuk perpustakaan pihak ke-3.C ++ 17 sekarang memiliki
std::filesystem::directory_iterator
, yang dapat digunakan sebagaiJuga,
std::filesystem::recursive_directory_iterator
dapat mengulangi subdirektori juga.sumber
namespace fs = std::experimental::filesystem;
. Tampaknya berfungsi ok.std::filesystem::path
kestd::cout
, tanda kutip termasuk dalam output. Untuk menghindarinya, tambahkan.string()
jalur untuk melakukan konversi eksplisit dan bukan implisit (di sinistd::cout << p.string() << std::endl;
). Contoh: coliru.stacked-crooked.com/view?id=a55ea60bbd36a8a3std::wstring
boleh digunakan atau apa jenis dari iterator?-lstdc++fs
, saya akan mendapatkanSIGSEGV (Address boundary error)
. Saya tidak dapat menemukan di mana pun dalam dokumentasi bahwa ini diperlukan, dan tautan tidak memberikan petunjuk apa pun. Ini bekerja untuk keduanyag++ 8.3.0
danclang 8.0.0-3
. Apakah ada yang punya wawasan ke mana hal-hal seperti ini ditentukan dalam dokumen / spesifikasi?Sayangnya standar C ++ tidak mendefinisikan cara standar untuk bekerja dengan file dan folder dengan cara ini.
Karena tidak ada cara lintas platform, cara lintas platform terbaik adalah dengan menggunakan perpustakaan seperti modul sistem file boost .
Metode peningkatan lintas platform:
Sumber dari halaman boost yang disebutkan di atas.
Untuk sistem berbasis Unix / Linux:
Anda dapat menggunakan opendir / readdir / closedir .
Kode sumber dari halaman manual di atas.
Untuk sistem berbasis windows:
Anda dapat menggunakan fungsi Win32 API FindFirstFile / FindNextFile / FindClose .
Kode sumber dari halaman msdn di atas.
sumber
FindFirstFile(TEXT("D:\\IMAGE\\MYDIRECTORY\\*"), &findFileData);
std::experimental::filesystem
, dengan C ++ 17 adastd::filesystem
, yang memiliki fungsi yang sama dengan boost (libs berasal dari boost). Lihat jawaban Shreevardhan di bawah ini.Satu fungsi sudah cukup, Anda tidak perlu menggunakan perpustakaan pihak ke-3 (untuk Windows).
PS: seperti yang disebutkan oleh @Sebastian, Anda bisa mengubah
*.*
ke*.ext
untuk mendapatkan hanya file EXT (yaitu dari jenis tertentu) di direktori itu.sumber
std::vector<std::wstring>
danfileName.c_str()
bukannya vektor string, yang tidak akan dikompilasi.Untuk solusi C saja, silakan periksa ini. Hanya membutuhkan tajuk tambahan:
https://github.com/cxong/tinydir
Beberapa keunggulan dibandingkan opsi lain:
readdir_r
mana tersedia, yang berarti itu (biasanya) threadsafeUNICODE
makro yang samasumber
Saya sarankan menggunakan
glob
pembungkus yang dapat digunakan kembali ini. Ini menghasilkan yangvector<string>
sesuai dengan jalur file yang sesuai dengan pola glob:Yang kemudian dapat dipanggil dengan pola wildcard sistem normal seperti:
sumber
No such file or directory
. Bisakah Anda memberi tahu saya cara mengatasi masalah ini?GLOB_TILDE
denganGLOB_TILDE | GLOB_MARK
dan kemudian memeriksa jalur yang berakhir dengan garis miring. Anda harus membuat modifikasi untuk itu jika Anda membutuhkannya.glob
.Berikut ini adalah kode yang sangat sederhana dalam
C++11
menggunakanboost::filesystem
perpustakaan untuk mendapatkan nama file dalam direktori (tidak termasuk nama folder):Outputnya seperti:
sumber
boost::filesystem
perpustakaan boost.org/doc/libs/1_58_0/libs/filesystem/doc/index.htmKenapa tidak digunakan
glob()
?sumber
Saya pikir, cuplikan di bawah ini dapat digunakan untuk mendaftar semua file.
Berikut ini adalah struktur dari dirent
sumber
Coba tingkatkan untuk metode x-platform
http://www.boost.org/doc/libs/1_38_0/libs/filesystem/doc/index.htm
atau cukup gunakan file hal spesifik OS Anda.
sumber
Lihat kelas ini yang menggunakan api win32. Cukup buat instance dengan menyediakan
foldername
dari mana Anda ingin listing kemudian panggilgetNextFile
metode untuk mendapatkan yang berikutnyafilename
dari direktori. Saya pikir itu perluwindows.h
danstdio.h
.sumber
Manual GNU FTW
http://www.gnu.org/software/libc/manual/html_node/Simple-Directory-Lister.html#Simple-Directory-Lister
Juga, kadang-kadang ada baiknya langsung ke sumbernya (pun intended). Anda dapat belajar banyak dengan melihat jeroan dari beberapa perintah yang paling umum di Linux. Saya telah membuat mirror sederhana dari GNU's coreutils di github (untuk membaca).
https://github.com/homer6/gnu_coreutils/blob/master/src/ls.c
Mungkin ini tidak membahas Windows, tetapi sejumlah kasus menggunakan varian Unix dapat diperoleh dengan menggunakan metode ini.
Semoga itu bisa membantu ...
sumber
Jawaban Shreevardhan bekerja dengan sangat baik. Tetapi jika Anda ingin menggunakannya di c ++ 14, lakukan saja perubahan
namespace fs = experimental::filesystem;
yaitu,
sumber
sumber
Saya harap kode ini membantu Anda.
sumber
string2wchar_t
mengembalikan alamat variabel lokal. Juga, Anda mungkin harus menggunakan metode konversi yang tersedia di WinAPI alih-alih menulis metode Anda sendiri.Implementasi ini mewujudkan tujuan Anda, secara dinamis mengisi serangkaian string dengan konten direktori yang ditentukan.
sumber
if
blok pertama . Saya menyebutnya denganchar **list; int numItems; exploreDirectory("/folder",list, numItems);
Ini bekerja untuk saya. Maaf jika saya tidak dapat mengingat sumbernya. Mungkin dari halaman manual.
sumber
Anda bisa mendapatkan semua file langsung di direktori root Anda dengan menggunakan std :: experimental :: filesystem :: directory_iterator (). Kemudian, baca nama pathfiles ini.
sumber
Jawaban ini seharusnya berfungsi untuk pengguna Windows yang mengalami kesulitan dalam menjalankan ini dengan Visual Studio dengan jawaban lain mana pun.
Unduh file dirent.h dari halaman github. Tetapi lebih baik hanya menggunakan file Raw dirent.h dan ikuti langkah-langkah saya di bawah ini (ini adalah cara saya membuatnya bekerja).
Halaman Github untuk dirent.h untuk Windows: Halaman Github untuk dirent.h
Raw Dirent File: Raw dirent.h File
Buka proyek Anda dan Tambahkan Item baru ( Ctrl+ Shift+ A). Tambahkan file header (.h) dan beri nama dirent.h.
Tempel kode file Raw dirent.h ke dalam header Anda.
Sertakan "dirent.h" dalam kode Anda.
Masukkan
void filefinder()
metode di bawah ini dalam kode Anda dan panggil darimain
fungsi Anda atau edit fungsi bagaimana Anda ingin menggunakannya.sumber
Sebut saja sistem itu!
Kemudian baca saja file tersebut.
EDIT: Jawaban ini harus dianggap sebagai peretasan, tetapi ini benar-benar berfungsi (walaupun dengan cara khusus platform) jika Anda tidak memiliki akses ke solusi yang lebih elegan.
sumber
Karena file dan sub direktori direktori umumnya disimpan dalam struktur pohon, cara intuitif adalah dengan menggunakan algoritma DFS untuk secara rekursif melintasi masing-masing. Berikut adalah contoh dalam sistem operasi windows dengan menggunakan fungsi file dasar di io.h. Anda dapat mengganti fungsi-fungsi ini di platform lain. Yang ingin saya ungkapkan adalah bahwa ide dasar DFS memenuhi masalah ini dengan sempurna.
sumber
Saya mencoba mengikuti contoh yang diberikan di kedua jawaban dan mungkin perlu dicatat bahwa tampaknya seolah-olah
std::filesystem::directory_entry
telah diubah untuk tidak memiliki kelebihan<<
operator. Alih-alihstd::cout << p << std::endl;
saya harus menggunakan yang berikut ini untuk dapat mengkompilasi dan membuatnya berfungsi:mencoba meneruskan
p
sendiri untukstd::cout <<
menghasilkan kesalahan kelebihan yang hilang.sumber
Membangun apa yang diposting oleh herohuyongtao dan beberapa posting lainnya:
http://www.cplusplus.com/forum/general/39766/
Apa tipe input yang diharapkan dari FindFirstFile?
Bagaimana cara mengubah wstring menjadi string?
Ini adalah solusi Windows.
Karena saya ingin meneruskan std :: string dan mengembalikan vektor string, saya harus membuat beberapa konversi.
sumber
WIN32_FIND_DATAA
,FindFirstFileA
danFindNextFileA
. Maka Tidak perlu mengubah hasil menjadi multibyte atau Input ke unicode.Hanya sesuatu yang ingin saya bagikan dan terima kasih atas bahan bacaannya. Bermain-main dengan fungsi untuk sedikit memahaminya. Anda mungkin menyukainya. e berdiri untuk ekstensi, p adalah untuk path, dan s adalah untuk path separator.
Jika jalur dilewatkan tanpa mengakhiri pemisah, pemisah akan ditambahkan ke jalur. Untuk ekstensi, jika string kosong dimasukkan maka fungsi akan mengembalikan file apa pun yang tidak memiliki ekstensi dalam namanya. Jika satu bintang dimasukkan dari semua file dalam direktori akan dikembalikan. Jika panjang e lebih besar dari 0 tetapi bukan satu * maka titik akan ditambahkan ke e jika e tidak mengandung titik di posisi nol.
Untuk nilai kembali. Jika peta nol panjang dikembalikan maka tidak ada yang ditemukan tetapi direktori terbuka oke. Jika indeks 999 tersedia dari nilai kembali tetapi ukuran peta hanya 1 maka itu berarti ada masalah dengan membuka jalur direktori.
Perhatikan bahwa untuk efisiensi, fungsi ini dapat dibagi menjadi 3 fungsi yang lebih kecil. Selain itu, Anda dapat membuat fungsi pemanggil yang akan mendeteksi fungsi mana yang akan dipanggil berdasarkan input. Mengapa itu lebih efisien? Mengatakan jika Anda akan mengambil semua yang merupakan file, melakukan metode itu subfungsi yang dibangun untuk mengambil semua file hanya akan mengambil semua file dan tidak perlu mengevaluasi kondisi lain yang tidak perlu setiap kali ditemukan file.
Itu juga berlaku ketika Anda mengambil file yang tidak memiliki ekstensi. Fungsi dibangun khusus untuk tujuan itu hanya akan mengevaluasi cuaca jika objek yang ditemukan adalah file dan kemudian apakah nama file memiliki titik di dalamnya.
Penghematan mungkin tidak banyak jika Anda hanya membaca direktori dengan tidak banyak file. Tetapi jika Anda membaca sejumlah besar direktori atau jika direktori tersebut memiliki beberapa ratus ribu file, ini bisa menjadi penghematan besar.
sumber
sumber
Ini berhasil untuk saya. Itu menulis file dengan hanya nama (tidak ada jalur) dari semua file. Kemudian ia membaca file txt itu dan mencetaknya untuk Anda.
sumber