简体   繁体   中英

C++ How Do I Read All .txt Files in a Directory?

How do I read all .txt files in a certain directory? Let's say in my C:\\ I have a foo.txt and a foo2.txt . Is there a way to read both of these two without having to do something like this?

string text;
string text2;

ifstream myFile ("foo.txt");
ifstream myFile2 ("foo2.txt");

while(myFile << text){
};

while(myFile2 << text2){
};

In other words, is it possible to put a wildcard *.txt to instruct to read all .txt files?

ifstream myFile ("*.txt");

You'd typically do this by passing the name(s) of the files to read on the command line. Using a Linux-like shell, passing something like foo *.txt will be expanded by the shell, so foo will receive the names of the appropriate files in its argc / argv . On Windows, the shell doesn't do that, but if you're using vc++, you can link in setargv.obj to have to done automatically.

Once you've done that, you receive the file names in argc / argv , and process them from there:

int main(int argc, char **argv) { 
    if (argc < 2) {
        std::cerr << "Usage: process <filename> [filename...]\n";
        return EXIT_FAILURE;
    }

    for (int i=1; i<argc; i++) {
        std::ifstream infile(argv[i]);
        // process file
    }
}

Since I see you are using windows here is a FindFirstFile , FindNextFile . Do not have Windows machine handy so I cannot give you example but here are the resources:

FindFirstFile FindNextFile

You can than extract file name for ifstream.

Or you can use C++17 directory iterator . I have not played with this at all.

How do I read any .txt files in a certain directory?

The C++11 (see n3337 ) and C++14 standards do not know about directories . You could have a system without directories (even if it is not common today; however early MS-DOS 1 did not have directories), and you can have many different file systems .

You need support from your operating system on directories. Remember that a C++ implementation could (in theory) exist on a computer without any OS.

Even the notion of file streams (in the C++ language specification) is not required to be related to operating system files (see this ); however on most C++ implementations it is practically related.

C++17 is adding a standard header <filesystem> for file systems. However, many C++ implementations don't support that yet. Please refer to the documentation of your C++ implementation and of your system.

In practice, you need support from your OS to deal with directories. You could use some framework like Boost , Qt , POCO for that. They practically are wrapping operating-system specific services or system calls related to directories.

And the notion of directory varies (in the details) with OSes and with file systems: a directory on Windows is not the same as a directory on Linux. Even the notion of working directory is slightly different.

On Linux and POSIX, see opendir(3) , readdir(3) , realpath(3) , dirname(3) , nftw(3) , getcwd(3) , stat(2) , chdir(2) , chroot(2) , mkdir(2) etc... to deal with directories (see also path_resolution(7) ). On Windows, it is different (see GRC's answer ).

In other words, is it possible to put an asterisk next to .txt and say read all .txt files?
ifstream myFile ("*.txt");

Probably not, and it does not make any sense . Do you want to iterate on several files (then you won't deal with a single ifstream )? Do you dream of some magic mechanism -which does not exist in practice- which would concatenate all files whose name ends with .txt ? In what order? What should happen if some other process is adding or removing files in that directory at the same time? What should happen with a directory which does not contain any file whose name ends with .txt ? What about a directory containing zillions of files and terabytes of data (your hardware would need hours or days to read them all!)?

On some operating systems (notably Linux), *.txt is a valid file path (of course, it smells bad and usually nobody creates such files on purpose; but it is in principle possible to create such a file). What behavior would you expect in that case? What about an hypothetical working directory contain both a *.txt file and some a.txt and b.txt ? BTW, on Linux a file is really an inode(7) and the same file could have several file paths (see link(2) ...) or even none of them.

Read also about globbing (which works differently on various OSes: on Unix systems, it is often done by the shell . In my incomplete understanding, on Windows, it might be done by some crt0 -like startup routine).

Take several days or weeks to read Operating Systems : Three Easy Pieces to understand better the role of an OS.

The constructor of ifstream accepts only one file.

Also please refer to Google first before asking any question to avoid multiple questions

No, you cannot pass "*.txt" to the constructor of ifstream and expect to read the content of the two files. Also you don't need two objects, using the same object you can read the content of the two files, one after the other.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM