ฉันจะกำหนดรายการไฟล์ในไดเรกทอรีจากภายในรหัส C หรือ C ++ ได้อย่างไร
ฉันไม่ได้รับอนุญาตให้ดำเนินการls
คำสั่งและแยกผลลัพธ์จากภายในโปรแกรมของฉัน
stat()
ข้อผิดพลาด readdir()
'ไม่มีไฟล์หรือไดเรกทอรีดังกล่าวเมื่อชื่อไฟล์จะถูกส่งกลับโดย
ฉันจะกำหนดรายการไฟล์ในไดเรกทอรีจากภายในรหัส C หรือ C ++ ได้อย่างไร
ฉันไม่ได้รับอนุญาตให้ดำเนินการls
คำสั่งและแยกผลลัพธ์จากภายในโปรแกรมของฉัน
stat()
ข้อผิดพลาด readdir()
'ไม่มีไฟล์หรือไดเรกทอรีดังกล่าวเมื่อชื่อไฟล์จะถูกส่งกลับโดย
คำตอบ:
ในงานขนาดเล็กและเรียบง่ายที่ฉันไม่ได้ใช้บูสต์ฉันใช้dirent.hซึ่งใช้ได้กับ 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;
}
มันเป็นไฟล์ส่วนหัวขนาดเล็กและทำสิ่งที่ง่ายที่สุดที่คุณต้องการโดยไม่ต้องใช้วิธีการที่ใช้เทมเพลตขนาดใหญ่เช่นการเพิ่ม (ไม่มีความผิดฉันชอบการเพิ่ม!)
ผู้เขียนเลเยอร์ความเข้ากันได้ของ windows คือ Toni Ronkko ใน Unix เป็นส่วนหัวมาตรฐาน
อัพเดท 2017 :
ใน C ++ 17 std::filesystem
ตอนนี้จะมีวิธีการอย่างเป็นทางการไปยังแฟ้มรายชื่อของระบบไฟล์ของคุณ: มีคำตอบที่ยอดเยี่ยมจากShreevardhanด้านล่างด้วยรหัสแหล่งที่มานี้:
#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
ด้วยภาษา C ++ 17 std::filesystem
มี ดูคำตอบของ Shreevardhan ด้านล่าง ดังนั้นไม่จำเป็นต้องใช้ห้องสมุดบุคคลที่สาม
C ++ 17 ตอนนี้มี a std::filesystem::directory_iterator
ซึ่งสามารถใช้เป็น
#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::filesystem::recursive_directory_iterator
สามารถทำซ้ำไดเรกทอรีย่อยได้เช่นกัน
namespace fs = std::experimental::filesystem;
แต่มีก็ยังคงทดลอง: มันดูเหมือนว่าจะโอเค
std::filesystem::path
ไปstd::cout
เครื่องหมายคำพูดจะรวมอยู่ในผลลัพธ์ เพื่อหลีกเลี่ยงปัญหานั้นให้ผนวก.string()
เส้นทางเพื่อทำการแปลงอย่างชัดเจนแทนการแปลงโดยนัย (ที่นี่std::cout << p.string() << std::endl;
) ตัวอย่าง: coliru.stacked-crooked.com/view?id=a55ea60bbd36a8a3
std::wstring
ใช้หรือเป็นชนิดจากตัววนซ้ำ
-lstdc++fs
SIGSEGV (Address boundary error)
ฉันไม่พบที่ใดก็ได้ในเอกสารที่จำเป็นต้องใช้และตัวเชื่อมโยงก็ไม่ได้ให้เงื่อนงำใด ๆ นี้ทำงานให้กับทั้งสองและg++ 8.3.0
clang 8.0.0-3
ใครบ้างมีความเข้าใจอย่างถ่องแท้ว่าสิ่งใดที่ระบุไว้ในเอกสาร / รายละเอียด?
น่าเสียดายที่มาตรฐาน C ++ ไม่ได้กำหนดวิธีการมาตรฐานในการทำงานกับไฟล์และโฟลเดอร์ด้วยวิธีนี้
เนื่องจากไม่มีทางข้ามแพลตฟอร์มวิธีข้ามแพลตฟอร์มที่ดีที่สุดคือการใช้ห้องสมุดเช่นโมดูลเพิ่มระบบแฟ้ม
วิธีการเพิ่มข้ามแพลตฟอร์ม:
ฟังก์ชั่นต่อไปนี้ให้เส้นทางไดเรกทอรีและชื่อไฟล์ค้นหาไดเรกทอรีและไดเรกทอรีย่อยซ้ำเพื่อค้นหาชื่อไฟล์กลับบูลและหากประสบความสำเร็จเส้นทางไปยังไฟล์ที่พบ
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; }
แหล่งที่มาจากหน้าเพิ่มที่กล่าวถึงข้างต้น
สำหรับระบบที่ใช้ Unix / Linux:
คุณสามารถใช้opendir / readdir / closedir
โค้ดตัวอย่างที่ค้นหาไดเรกทอรีสำหรับรายการ `` ชื่อ '' คือ:
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;
ซอร์สโค้ดจาก man page ด้านบน
สำหรับระบบที่ใช้ windows:
คุณสามารถใช้ Win32 API FindFirstFile / FindNextFile / FindCloseฟังก์ชั่น
ตัวอย่าง C ++ ต่อไปนี้แสดงการใช้ 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); } }
ซอร์สโค้ดจากหน้า msdn ด้านบน
FindFirstFile(TEXT("D:\\IMAGE\\MYDIRECTORY\\*"), &findFileData);
std::experimental::filesystem
ด้วย C ++ 17 นั่นคือstd::filesystem
ซึ่งมีฟังก์ชั่นที่คล้ายกันเช่นการเพิ่ม (libs ที่ได้มาจากการเพิ่ม) ดูคำตอบของ Shreevardhan ด้านล่าง
ฟังก์ชั่นเดียวก็เพียงพอแล้วคุณไม่จำเป็นต้องใช้ห้องสมุดบุคคลที่สาม (สำหรับ 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: ตามที่กล่าวถึงโดย @Sebastian คุณสามารถเปลี่ยน*.*
เป็น*.ext
เพื่อรับเฉพาะไฟล์ EXT (เช่นประเภทที่ระบุ) ในไดเรกทอรีนั้น
std::vector<std::wstring>
แล้วfileName.c_str()
แทนเวกเตอร์ของสตริงซึ่งจะไม่คอมไพล์
สำหรับวิธีการแก้ปัญหา C เท่านั้นโปรดตรวจสอบนี้ ต้องการเพียงส่วนหัวเพิ่มเติมเท่านั้น:
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);
ข้อดีกว่าตัวเลือกอื่น ๆ :
readdir_r
กรณีที่มีให้ซึ่งหมายความว่าเป็น threadsafe (ปกติ)UNICODE
มาโครตัวเดียวกันฉันแนะนำให้ใช้glob
กับ wrapper ที่ใช้ซ้ำได้นี้ มันสร้างที่vector<string>
สอดคล้องกับเส้นทางของไฟล์ที่เหมาะสมกับรูปแบบ glob:
#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;
}
ซึ่งสามารถเรียกด้วยรูปแบบสัญลักษณ์แทนระบบปกติเช่น:
vector<string> files = globVector("./*");
No such file or directory
มันบอกว่า คุณช่วยบอกฉันได้ไหมว่าจะแก้ปัญหานี้ได้อย่างไร?
GLOB_TILDE
กับGLOB_TILDE | GLOB_MARK
แล้วตรวจสอบเส้นทางที่ลงท้ายด้วยเครื่องหมายทับ คุณจะต้องทำการแก้ไขหากคุณต้องการ
glob
แต่น่าเสียดายที่คุณไม่สามารถหาไฟล์ที่ซ่อนอยู่อย่างสม่ำเสมอผ่าน
นี่คือรหัสง่ายๆในการC++11
ใช้boost::filesystem
ไลบรารีเพื่อรับชื่อไฟล์ในไดเรกทอรี (ยกเว้นชื่อโฟลเดอร์):
#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;
}
}
ผลผลิตเป็นเช่น:
file1.txt
file2.dat
boost::filesystem
ห้องสมุดของพวกเขาboost.org/doc/libs/1_58_0/libs/filesystem/doc/index.htm
ทำไมไม่ใช้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;
}
ฉันคิดว่าตัวอย่างด้านล่างสามารถใช้เพื่อแสดงรายการไฟล์ทั้งหมด
#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);
}
ต่อไปนี้เป็นโครงสร้างของ struct dirent
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 */
};
ลองเพิ่มประสิทธิภาพสำหรับวิธีการ x-platform
http://www.boost.org/doc/libs/1_38_0/libs/filesystem/doc/index.htm
หรือเพียงแค่ใช้ไฟล์เฉพาะระบบปฏิบัติการของคุณ
ลองดูคลาสนี้ที่ใช้ win32 api เพียงสร้างอินสแตนซ์โดยระบุสิ่งfoldername
ที่คุณต้องการให้รายชื่อจากนั้นเรียกใช้getNextFile
เมธอดเพื่อรับสิ่งต่อไปfilename
จากไดเรกทอรี ฉันคิดว่ามันตอบสนองความต้องการและwindows.h
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 FTW
นอกจากนี้บางครั้งก็เป็นการดีที่จะไปยังแหล่งข้อมูล (ตั้งใจให้เล่น) คุณสามารถเรียนรู้ได้มากมายโดยดูที่คำสั่งที่พบบ่อยที่สุดใน Linux ฉันได้ตั้งค่ากระจกเรียบง่ายของ coreutils ของ GNU บน github (สำหรับการอ่าน)
https://github.com/homer6/gnu_coreutils/blob/master/src/ls.c
บางทีนี่อาจไม่ได้อยู่ที่ Windows แต่มีหลายกรณีที่ใช้ Unix Variants โดยใช้วิธีการเหล่านี้
หวังว่าจะช่วย ...
คำตอบของ Shreevardhan ใช้งานได้ดี แต่ถ้าคุณต้องการใช้ใน c ++ 14 เพียงแค่ทำการเปลี่ยนแปลงnamespace fs = experimental::filesystem;
กล่าวคือ
#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;
}
ฉันหวังว่ารหัสนี้จะช่วยคุณ
#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
ส่งคืนที่อยู่ของตัวแปรท้องถิ่น นอกจากนี้คุณควรใช้วิธีการแปลงที่มีอยู่ใน WinAPI แทนที่จะเขียนวิธีของคุณเอง
การใช้งานนี้ตระหนักถึงวัตถุประสงค์ของคุณเติมอาร์เรย์ของสตริงแบบไดนามิกด้วยเนื้อหาของไดเรกทอรีที่ระบุ
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
บล็อกแรก ฉันกำลังโทรหาด้วยchar **list; int numItems; exploreDirectory("/folder",list, numItems);
มันใช้งานได้สำหรับฉัน ฉันขอโทษถ้าฉันจำแหล่งที่ไม่ได้ มันอาจมาจากหน้าคน
#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/");
}
คุณสามารถรับไฟล์ทั้งหมดในไดเรคทอรีรูทของคุณโดยใช้ std :: experiment :: filesystem :: directory_iterator () จากนั้นอ่านชื่อของไฟล์พา ธ เหล่านี้
#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;
}
คำตอบนี้ควรใช้ได้กับผู้ใช้ Windows ที่มีปัญหาในการทำงานกับ Visual Studio ด้วยคำตอบอื่น ๆ
ดาวน์โหลดไฟล์ dirent.h จากหน้า github แต่ดีกว่าที่จะใช้ไฟล์ Raw dirent.h และทำตามขั้นตอนของฉันด้านล่าง (เป็นวิธีที่ทำให้ฉันใช้งานได้)
หน้า Github สำหรับ dirent.h สำหรับ Windows: หน้า Github สำหรับ dirent.h
ไฟล์Raw Dirent : ไฟล์Raw dirent.h
ไปที่โครงการของคุณและเพิ่มรายการใหม่ ( Ctrl+ Shift+ A) เพิ่มไฟล์ส่วนหัว (.h) และตั้งชื่อ dirent.h
วางรหัสไฟล์ดิบ dirent.hลงในส่วนหัวของคุณ
รวม "dirent.h" ในรหัสของคุณ
ใส่void filefinder()
วิธีการด้านล่างในรหัสของคุณและเรียกมันจากmain
ฟังก์ชั่นของคุณหรือแก้ไขฟังก์ชั่นวิธีที่คุณต้องการใช้
#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( "dir /b /s /a-d * > file_names.txt" );
จากนั้นเพียงแค่อ่านไฟล์
แก้ไข: คำตอบนี้ควรพิจารณาว่าเป็นการแฮ็ก แต่มันใช้งานได้จริง (แม้ว่าจะเป็นวิธีเฉพาะของแพลตฟอร์ม) หากคุณไม่สามารถเข้าถึงโซลูชันที่หรูหรากว่านี้ได้
เนื่องจากไฟล์และไดเรกทอรีย่อยของไดเรกทอรีโดยทั่วไปจะถูกเก็บไว้ในโครงสร้างแบบต้นไม้วิธีที่ง่ายคือการใช้อัลกอริทึม DFS เพื่อวนซ้ำแต่ละไฟล์ นี่คือตัวอย่างในระบบปฏิบัติการ windows โดยใช้ฟังก์ชันไฟล์พื้นฐานใน io.h คุณสามารถแทนที่ฟังก์ชั่นเหล่านี้ในแพลตฟอร์มอื่น สิ่งที่ฉันต้องการแสดงคือความคิดพื้นฐานของ DFS ตรงกับปัญหานี้อย่างสมบูรณ์
#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);
}
ผมพยายามที่จะทำตามตัวอย่างที่ให้ไว้ในทั้ง คำตอบและมันอาจจะเป็นที่น่าสังเกตว่ามันดูราวกับว่าstd::filesystem::directory_entry
ได้ถูกเปลี่ยนไปไม่ได้เกินของ<<
ผู้ประกอบการ แทนที่จะstd::cout << p << std::endl;
ต้องใช้สิ่งต่อไปนี้เพื่อรวบรวมและทำให้มันใช้งานได้:
#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;
}
การพยายามส่งp
ด้วยตนเองเพื่อstd::cout <<
ให้เกิดข้อผิดพลาดโอเวอร์โหลดที่ขาดหายไป
สร้างสิ่งที่ herohuyongtao โพสต์และโพสต์อื่น ๆ :
http://www.cplusplus.com/forum/general/39766/
ประเภทการป้อนข้อมูลที่คาดหวังของ FindFirstFile คืออะไร
วิธีการแปลง wstring เป็นสตริง?
นี่คือโซลูชัน Windows
เนื่องจากฉันต้องการส่งผ่าน std :: string และส่งคืนเวกเตอร์ของสตริงฉันจึงต้องทำการแปลงสองสามครั้ง
#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
, และFindFirstFileA
FindNextFileA
จากนั้นไม่จำเป็นต้องแปลงผลลัพธ์เป็นหลายไบต์หรือป้อนเป็น Unicode
เป็นเพียงสิ่งที่ฉันต้องการแบ่งปันและขอขอบคุณสำหรับเนื้อหาการอ่าน ลองฟังด้วยฟังก์ชั่นสักหน่อยเพื่อทำความเข้าใจ คุณอาจจะชอบมัน e ย่อมาจากส่วนขยาย p เป็นเส้นทางและ s สำหรับตัวคั่นเส้นทาง
หากเส้นทางถูกส่งโดยไม่มีตัวคั่นสิ้นสุดตัวคั่นจะถูกผนวกเข้ากับเส้นทาง สำหรับส่วนขยายหากมีการป้อนสตริงว่างฟังก์ชันจะส่งคืนไฟล์ใด ๆ ที่ไม่มีนามสกุลในชื่อ หากใส่ดาวดวงเดียวมากกว่าไฟล์ทั้งหมดในไดเรกทอรีจะถูกส่งคืน หากความยาว e มากกว่า 0 แต่ไม่ใช่เพียงหนึ่งเดียว * จุดนั้นจะถูกเติมให้เป็น e หาก e ไม่มีจุดที่ตำแหน่งศูนย์
สำหรับค่าส่งคืน หากส่งคืนแผนที่ที่มีความยาวเป็นศูนย์จะไม่พบสิ่งใดนอกจากไดเรกทอรีนั้นเปิดอยู่ หากดัชนี 999 พร้อมใช้งานจากค่าส่งคืน แต่ขนาดของแผนที่เป็นเพียง 1 นั่นหมายความว่ามีปัญหากับการเปิดเส้นทางไดเรกทอรี
โปรดทราบว่าเพื่อประสิทธิภาพฟังก์ชั่นนี้สามารถแบ่งออกเป็น 3 ฟังก์ชั่นขนาดเล็ก ด้านบนของที่คุณสามารถสร้างฟังก์ชั่นการโทรที่จะตรวจสอบฟังก์ชั่นที่มันจะเรียกตามอินพุต ทำไมจึงมีประสิทธิภาพมากกว่า กล่าวว่าหากคุณกำลังจะคว้าทุกอย่างที่เป็นไฟล์การทำวิธีการนั้นเป็นฟังก์ชั่นย่อยที่สร้างขึ้นเพื่อคว้าไฟล์ทั้งหมดจะเพิ่งคว้าทุกสิ่งที่เป็นไฟล์และไม่จำเป็นต้องประเมินเงื่อนไขที่ไม่จำเป็นอื่น ๆ ทุกครั้งที่พบไฟล์
ซึ่งจะนำไปใช้เมื่อคุณคว้าไฟล์ที่ไม่มีส่วนขยาย ฟังก์ชั่นที่สร้างขึ้นเฉพาะสำหรับวัตถุประสงค์นั้นจะประเมินสภาพอากาศเฉพาะเมื่อวัตถุที่พบนั้นเป็นไฟล์และถ้าชื่อไฟล์นั้นมีจุดอยู่ในนั้นหรือไม่
การบันทึกอาจไม่มากถ้าคุณอ่านเฉพาะไดเรกทอรีที่มีไฟล์ไม่มาก แต่ถ้าคุณกำลังอ่านไดเรกทอรีจำนวนมากหรือถ้าไดเรกทอรีมีไฟล์สองแสนไฟล์มันอาจเป็นการประหยัดขนาดใหญ่
#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;
}
สิ่งนี้ใช้ได้สำหรับฉัน มันเขียนไฟล์ที่มีชื่อ (ไม่มีเส้นทาง) ของไฟล์ทั้งหมด จากนั้นจะอ่านไฟล์ txt นั้นและพิมพ์ให้คุณ
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;
}
}