简体   繁体   English

C++如何为多个文件编写一个ifstream?

[英]C++ how to write a ifstream for multiple files?

So I have several files that form a contingent number of lines, so let's call them file1, file2, file3 and so forth.所以我有几个文件,它们形成了一个随机的行数,所以让我们称它们为 file1、file2、file3 等等。 What I want to do is to create a istream class which streams all the files as if they were one.我想要做的是创建一个 istream 类,它将所有文件作为一个流。 One thing i got is not to subclass std::istream but to reimplement streambuf.我得到的一件事不是对 std::istream 进行子类化,而是重新实现 streambuf。 My question is: how would I go about this - how would i be able to read from multiple files without having them all in memory?我的问题是:我将如何解决这个问题 - 我如何能够从多个文件中读取而不将它们全部存储在内存中?

Is it possible to make an istream that reads multiple files?是否可以制作一个读取多个文件的istream

Yes, but you'll have to make it yourself.是的,但你必须自己做。 You can implement your own istream class by extending std::istream , and then implementing the methods it defines:您可以通过扩展std::istream来实现您自己的istream类,然后实现它定义的方法:

class custom_istream : public std::istream {
    std::ifstream underlying; 
    //... implement methods
};

The interface of std::istream is sufficiently flexible to allow you to do what you want. std::istream的接口足够灵活,可以让你做你想做的事。 However , implementing std::istream would require a lot of work, as you'd have to implement the entirety of the interface.但是,实现std::istream需要大量工作,因为您必须实现整个接口。

Is there an easier solution?有更简单的解决方案吗?

If you only need a subset of the functionality provided by std::istream , you could just write your own class.如果您只需要std::istream提供的功能的一个子集,您可以编写自己的类。

For example, if you only need to be able to read lines from the file, the below class will work just fine for multiple files:例如,如果您只需要能够从文件中读取行,下面的类将适用于多个文件:

class MultiFileReader {
    std::ifstream filestream; 
    std::ios_base::openmode mode;  
    size_t file_index = 0; 
    std::vector<std::string> filenames; 
    void open_next_file() {
        file_index++; 
        filestream = std::ifstream(filenames.at(file_index), mode); 
    }
   public:
    MultiFileReader(std::vector<std::string> const& files, std::ios_base::openmode mode)
      : filestream(files[0], mode), mode(mode) {}
    // Checks if there's no more files to open, and no more to read
    // in the current file
    bool hasMoreToRead() {
        if(file_index == filenames.size()) return false;
        if(file_index + 1 == filenames.size()) 
            return not filestream.eof(); 
        return true;
    }
    std::string read_line() {
        if(not hasMoreToRead()) {
            throw std::logic_error("No more to read"); 
        }
        // If at the end of the file, open the next file
        if(filestream.eof()) {
            open_next_file(); 
        }
        else {
            std::string line; 
            std::getline(filestream, line);
            return line; 
        }
    }
};  

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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