Làm thế nào để bạn lặp qua tất cả các tệp/thư mục đệ quy trong C++ chuẩn?Làm thế nào để bạn lặp qua tất cả các tệp/thư mục đệ quy trong C++ chuẩn?
Trả lời
Trong tiêu chuẩn C++, về mặt kỹ thuật không có cách nào để làm điều này kể từ khi chuẩn C++ không có quan niệm về thư mục. Nếu bạn muốn mở rộng mạng của mình một chút, bạn có thể muốn xem xét sử dụng Boost.FileSystem. Điều này đã được chấp nhận để đưa vào TR2, do đó, điều này mang đến cho bạn cơ hội tốt nhất để giữ cho việc triển khai của bạn càng gần với tiêu chuẩn càng tốt.
Một ví dụ, lấy trực tiếp từ trang web:
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;
}
C++ không có khái niệm về tệp? Điều gì về std :: fstream? Hoặc fopen? – Kevin
tệp, không phải thư mục –
Cập nhật liên quan đến phiên bản tăng mới nhất: Trong trường hợp bất cứ ai tình cờ gặp câu trả lời này, lần tăng mới nhất bao gồm tăng cường lớp tiện lợi :: recursive_directory_iterator để viết vòng lặp ở trên với cuộc gọi đệ quy rõ ràng không còn cần thiết nữa. Liên kết: http://www.boost.org/doc/libs/1_46_1/libs/filesystem/v3/doc/reference.html#Class-recursive_directory_iterator – JasDev
Bạn cần gọi các chức năng dành riêng cho hệ điều hành để duyệt qua hệ thống tệp, như open()
và readdir()
. Tiêu chuẩn C không chỉ định bất kỳ hàm liên quan đến hệ thống tập tin nào.
Còn C++ thì sao? Có bất kỳ chức năng nào như vậy trong iostream không? –
Chỉ dành cho tệp. Không có bất kỳ loại "hiển thị cho tôi tất cả các tập tin trong một thư mục" chức năng. –
@ 1800: Thư mục là các tệp. –
Bạn có thể muốn kiểm tra boost.filesystem
http://www.boost.org/doc/libs/1_31_0/libs/filesystem/doc/index.htm
Bạn không có. Standard C++ không hiển thị khái niệm về thư mục. Cụ thể là nó không cung cấp bất kỳ cách nào để liệt kê tất cả các tệp trong một thư mục.
Một cuộc tấn công khủng khiếp sẽ là sử dụng các cuộc gọi system() và phân tích cú pháp kết quả. Giải pháp hợp lý nhất là sử dụng một số loại thư viện đa nền tảng như Qt hoặc thậm chí POSIX.
Nếu sử dụng API Win32, bạn có thể sử dụng các chức năng FindFirstFile và FindNextFile.
http://msdn.microsoft.com/en-us/library/aa365200(VS.85).aspx
Đối traversal đệ quy các thư mục, bạn phải kiểm tra mỗi WIN32_FIND_DATA.dwFileAttributes để kiểm tra xem các bit FILE_ATTRIBUTE_DIRECTORY được thiết lập. Nếu bit được đặt thì bạn có thể đệ quy gọi hàm bằng thư mục đó. Ngoài ra, bạn có thể sử dụng một ngăn xếp để cung cấp cùng một hiệu ứng của một cuộc gọi đệ quy nhưng tránh tràn ngăn xếp cho cây con đường rất dài.
#include <windows.h>
#include <string>
#include <vector>
#include <stack>
#include <iostream>
using namespace std;
bool ListFiles(wstring path, wstring mask, vector<wstring>& files) {
HANDLE hFind = INVALID_HANDLE_VALUE;
WIN32_FIND_DATA ffd;
wstring spec;
stack<wstring> directories;
directories.push(path);
files.clear();
while (!directories.empty()) {
path = directories.top();
spec = path + L"\\" + mask;
directories.pop();
hFind = FindFirstFile(spec.c_str(), &ffd);
if (hFind == INVALID_HANDLE_VALUE) {
return false;
}
do {
if (wcscmp(ffd.cFileName, L".") != 0 &&
wcscmp(ffd.cFileName, L"..") != 0) {
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
directories.push(path + L"\\" + ffd.cFileName);
}
else {
files.push_back(path + L"\\" + ffd.cFileName);
}
}
} while (FindNextFile(hFind, &ffd) != 0);
if (GetLastError() != ERROR_NO_MORE_FILES) {
FindClose(hFind);
return false;
}
FindClose(hFind);
hFind = INVALID_HANDLE_VALUE;
}
return true;
}
int main(int argc, char* argv[])
{
vector<wstring> files;
if (ListFiles(L"F:\\cvsrepos", L"*", files)) {
for (vector<wstring>::iterator it = files.begin();
it != files.end();
++it) {
wcout << it->c_str() << endl;
}
}
return 0;
}
Mất bao lâu để bạn viết nó? Tôi nghĩ rằng nó sẽ mất ít thời gian hơn để dán C++ vào python và làm điều đó trong một dòng. –
Đây là một giải pháp tốt, không đệ quy (đôi khi có ích!). –
Btw, nếu ai đó muốn chỉnh sửa chương trình một chút để chấp nhận tham số dòng lệnh argv [1] cho đường dẫn thay vì đường dẫn cứng ("F: \\ cvsrepos"), chữ ký cho main (int, char) sẽ thay đổi để wmain (int, wchar_t) như thế này: int wmain (int argc, wchar_t * argv []) – JasDev
Bạn không. Tiêu chuẩn C++ không có khái niệm về thư mục. Việc triển khai thực hiện để biến một chuỗi thành một xử lý tệp. Nội dung của chuỗi đó và những gì nó ánh xạ tới là hệ điều hành phụ thuộc. Hãy nhớ rằng C++ có thể được sử dụng để viết hệ điều hành đó, vì vậy nó được sử dụng ở mức yêu cầu làm thế nào để lặp qua một thư mục chưa được xác định (vì bạn đang viết mã quản lý thư mục).
Xem tài liệu API OS của bạn để biết cách thực hiện việc này. Nếu bạn cần phải di động, bạn sẽ phải có một bó của #ifdef s cho các hệ điều hành khác nhau.
Ngoài hệ thống tệp tăng :: đã đề cập ở trên, bạn có thể muốn kiểm tra wxWidgets::wxDir và Qt::QDir.
Cả wxWidgets và Qt đều là các khung công tác nền tảng C++ dựa trên mã nguồn mở.
wxDir
cung cấp cách linh hoạt để truyền tệp theo cách đệ quy bằng cách sử dụng Traverse()
hoặc hàm GetAllFiles()
đơn giản hơn.Bạn cũng có thể thực hiện traversal với các hàm GetFirst()
và GetNext()
(tôi giả định rằng Traverse() và GetAllFiles() là các trình bao bọc mà cuối cùng sử dụng các hàm GetFirst() và GetNext()).
QDir
cung cấp quyền truy cập vào cấu trúc thư mục và nội dung của chúng. Có nhiều cách để duyệt các thư mục với QDir. Bạn có thể lặp qua các nội dung thư mục (bao gồm các thư mục con) với QDirIterator đã được khởi tạo với cờ QDirIterator :: Subdirectories. Một cách khác là sử dụng hàm GetEntryList() của QDir và thực hiện một quá trình truyền đệ quy.
Đây là mã mẫu (được lấy từ here # Ví dụ 8-5) cho biết cách lặp qua tất cả các thư mục con.
#include <qapplication.h>
#include <qdir.h>
#include <iostream>
int main(int argc, char **argv)
{
QApplication a(argc, argv);
QDir currentDir = QDir::current();
currentDir.setFilter(QDir::Dirs);
QStringList entries = currentDir.entryList();
for(QStringList::ConstIterator entry=entries.begin(); entry!=entries.end(); ++entry)
{
std::cout << *entry << std::endl;
}
return 0;
}
Doxygen sử dụng QT làm lớp tương thích với hệ điều hành của nó. Các công cụ cốt lõi không sử dụng GUI ở tất cả các công cụ thư mục (và các công cụ khác). –
Giải pháp nhanh đang sử dụng thư viện Dirent.h của C.
đang làm việc đoạn từ Wikipedia:
#include <stdio.h>
#include <dirent.h>
int listdir(const char *path) {
struct dirent *entry;
DIR *dp;
dp = opendir(path);
if (dp == NULL) {
perror("opendir: Path does not exist or could not be read.");
return -1;
}
while ((entry = readdir(dp)))
puts(entry->d_name);
closedir(dp);
return 0;
}
Thường trình này không đệ quy. – user501138
Lưu ý tất cả: không hoạt động trên VC++. –
@TimCooper, tất nhiên là không, dirent là posix cụ thể. – Vorac
Bạn có thể làm cho nó thậm chí còn đơn giản hơn với C++11 dòng sản phẩm mới dựa for
và Boost:
#include <boost/filesystem.hpp>
using namespace boost::filesystem;
struct recursive_directory_range
{
typedef recursive_directory_iterator iterator;
recursive_directory_range(path p) : p_(p) {}
iterator begin() { return recursive_directory_iterator(p_); }
iterator end() { return recursive_directory_iterator(); }
path p_;
};
for (auto it : recursive_directory_range(dir_path))
{
std::cout << it << std::endl;
}
Bạn có thể sử dụng ftw(3)
or nftw(3)
đi bộ một hệ thống phân cấp hệ thống tập tin trong C hoặc C++ trên POSIX hệ thống.
https://github.com/six-k/dtreetrawl/blob/f7c1d320225ee754b96fef28bb0774a2c34b91b8/dtreetrawl.c#L473 có ví dụ về điều này. Mã này thực hiện thêm một vài thứ nữa, nhưng nó hoạt động một hướng dẫn tốt để sử dụng 'nftw()'. –
Boost :: hệ thống tập tin cung cấp recursive_directory_iterator, mà là khá thuận tiện cho công việc này:
#include "boost/filesystem.hpp"
#include <iostream>
boost::filesystem::recursive_directory_iterator end;
for (it("./"); it != end; ++it) {
std::cout << *it << std::endl;
}
Nếu bạn đang trên Windows, bạn có thể sử dụng cùng với FindFirstFile FindNextFile API. Bạn có thể sử dụng FindFileData.dwFileAttributes để kiểm tra xem một đường dẫn cụ thể có phải là một tệp hoặc một thư mục hay không. Nếu đó là một thư mục, bạn có thể lặp lại thuật toán một cách đệ quy.
Ở đây, tôi đã đặt cùng một số mã liệt kê tất cả các tệp trên máy tính Windows.
Trong C++ 11/14 với "Filesystem TS", các <experimental/filesystem>
header và range- for
bạn chỉ có thể làm điều này:
#include <experimental/filesystem>
using std::experimental::filesystem::recursive_directory_iterator;
...
for (auto& dirEntry : recursive_directory_iterator(myPath))
cout << dirEntry << endl;
Tránh sử dụng 'using', sử dụng' namespace' để thay thế. –
Và tại sao vậy? Tốt hơn cụ thể hơn là đưa vào những thứ bạn không sử dụng. –
Xem lại chỉnh sửa của tôi, tôi cũng đã thêm không gian tên bị thiếu. –
Bạn có lẽ sẽ là tốt nhất với một trong hai boost hoặc C++ 14 của hệ thống tập tin thử nghiệm. NẾU bạn đang phân tích cú pháp một thư mục nội bộ (ví dụ: được sử dụng cho chương trình của bạn để lưu trữ dữ liệu sau khi chương trình đã đóng), sau đó tạo tệp chỉ mục có chỉ mục nội dung tệp. Bằng cách này, bạn có thể sẽ cần phải sử dụng tăng trong tương lai, vì vậy nếu bạn không có nó được cài đặt, cài đặt nó! Thứ hai, bạn có thể sử dụng một trình biên dịch có điều kiện:
#ifdef WINDOWS //define WINDOWS in your code to compile for windows
mã tại https://stackoverflow.com/a/67336/7077165
#ifdef POSIX //unix, linux, etc.
#include <stdio.h>
#include <dirent.h>
int listdir(const char *path) {
struct dirent *entry;
DIR *dp;
dp = opendir(path);
if (dp == NULL) {
perror("opendir: Path does not exist or could not be read.");
return -1;
}
while ((entry = readdir(dp)))
puts(entry->d_name);
closedir(dp);
return 0;
}
#endif
#ifdef WINDOWS
#include <windows.h>
#include <string>
#include <vector>
#include <stack>
#include <iostream>
using namespace std;
bool ListFiles(wstring path, wstring mask, vector<wstring>& files) {
HANDLE hFind = INVALID_HANDLE_VALUE;
WIN32_FIND_DATA ffd;
wstring spec;
stack<wstring> directories;
directories.push(path);
files.clear();
while (!directories.empty()) {
path = directories.top();
spec = path + L"\\" + mask;
directories.pop();
hFind = FindFirstFile(spec.c_str(), &ffd);
if (hFind == INVALID_HANDLE_VALUE) {
return false;
}
do {
if (wcscmp(ffd.cFileName, L".") != 0 &&
wcscmp(ffd.cFileName, L"..") != 0) {
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
directories.push(path + L"\\" + ffd.cFileName);
}
else {
files.push_back(path + L"\\" + ffd.cFileName);
}
}
} while (FindNextFile(hFind, &ffd) != 0);
if (GetLastError() != ERROR_NO_MORE_FILES) {
FindClose(hFind);
return false;
}
FindClose(hFind);
hFind = INVALID_HANDLE_VALUE;
}
return true;
}
#endif
//so on and so forth.
- 1. Đệ quy lặp qua tất cả các tệp trong thư mục và thư mục con của nó trong Qt
- 2. Làm thế nào để đệ quy các thư mục đi qua trong C trên Windows
- 3. bash lặp qua tất cả tìm đệ quy trong thư mục con
- 4. Làm thế nào để đệ quy đi qua tất cả các thư mục con và đọc tệp?
- 5. PyQt4: Làm thế nào để bạn lặp tất cả các mục trong một QListWidget
- 6. Diff Một thư mục đệ quy, bỏ qua tất cả các tập tin nhị phân:
- 7. Lặp qua tất cả các Tài nguyên trong ResourceManager - C#
- 8. Làm thế nào để lặp qua tất cả các ký tự ASCII trong Bash?
- 9. Làm thế nào để lặp qua tất cả trừ mục cuối cùng của danh sách?
- 10. Làm thế nào để lặp đệ quy thông qua một cấu trúc file và đổi tên thư mục trong python
- 11. TCL: Tìm kiếm đệ quy các thư mục con để nguồn tất cả các tệp .tcl
- 12. Làm cách nào để liệt kê tất cả các tệp tga trong một thư mục (không đệ quy) trong Python?
- 13. Lấy danh sách tất cả các tệp trong thư mục (đệ quy)
- 14. làm thế nào để bạn lặp qua tất cả các hàng trong lưới kendoUI với bộ lọc
- 15. Làm thế nào để lặp qua tất cả các bảng trong MS Access DB
- 16. .gitignore bỏ qua tất cả các tệp sau đó đệ quy cho phép * .foo
- 17. Tìm tất cả các tệp .php trong thư mục đệ quy
- 18. Trong ExtJS, Làm thế nào bạn có thể lặp qua các mục menu?
- 19. Làm thế nào để loại bỏ thư mục đệ quy?
- 20. Mục tiêu- C - Lặp qua tất cả các thuộc tính trong một lớp?
- 21. Làm thế nào để lặp qua tất cả các thuộc tính XElement và nhận giá trị
- 22. lặp qua tất cả các ô trong UICollectionview
- 23. Cách tạo một hàm đệ quy để sao chép tất cả các tệp và thư mục
- 24. Làm cách nào để lặp qua tất cả các phương thức của một lớp trong Perl?
- 25. g ++ bao gồm tất cả/usr/include đệ quy
- 26. Làm thế nào để bạn lặp qua một mảng các mảng ký tự trong c?
- 27. Đệ quy in tất cả các tệp từ Vim
- 28. Làm thế nào để bạn tìm thấy tất cả các mô-đun và các lớp học trong một mô-đun, đệ quy?
- 29. Làm thế nào để lặp qua tất cả các thuộc tính của một lớp?
- 30. Đệ quy trong các báo cáo đã chuẩn bị
Không chuẩn C++: http://pocoproject.org/docs/Poco.DirectoryIterator.html –
này nên sớm nằm trong tiêu chuẩn thông qua [TS hệ thống tập tin] (http://en.cppreference.com/w/cpp/experimental/fs), với [recursive_directory_iterator] (http: //en.cppreference.com/w/cpp/thử nghiệm/fs/recursive_directory_iterator) –
Nếu sử dụng thư viện C chuẩn không nhận được cách gọi một chương trình C++ là 'chuẩn', [nftw()] (https: //linux.die .net/người đàn ông/3/nftw). Đây là một ví dụ thực tế (https://github.com/six-k/dtreetrawl/blob/f7c1d320225ee754b96fef28bb0774a2c34b91b8/dtreetrawl.c#L473) –