【问题标题】:C++ how to write a ifstream for multiple files?C ++如何为多个文件编写ifstream?
【发布时间】:2019-03-27 18:49:14
【问题描述】:

所以我有几个文件,这些文件形成了数量不定的行,所以我们称它们为 file1、file2、file3 等等。我想要做的是创建一个 istream 类,它将所有文件都流式传输,就好像它们是一个一样。我得到的一件事不是子类化 std::istream 而是重新实现 streambuf。我的问题是:我将如何解决这个问题 - 我如何能够从多个文件中读取而不将它们全部存储在内存中?

【问题讨论】:

  • "but to reimplement streambuf" 我怀疑这种限制是否合理可行。但是¯_(ツ)_/¯谁知道...
  • 不清楚您想如何读取多个文件。在您知道如何从多个文件中读取以及如何处理它们的内容之前,如何将其包装到 std::istream 接口中是次要的
  • “我怎么能从多个文件中读取而不将它们全部保存在内存中” - 我怀疑你是否能够做到,而其中至少有 部分记忆。您将如何阅读无法阅读的内容?
  • 我自己有点挣扎,这可能没有意义。所以这里有一个初步的“想法”它是如何工作的:创建一个缓冲区,将文件流式传输到缓冲区中,如果一个文件完成并且缓冲区还有空间 - 开始将另一个文件加载到其中。我自己对这个想法有点怀疑,并问自己这是否是好的设计,因此问。
  • 您想按什么顺序阅读内容?如果是一个接一个的文件,你不必自己写任何东西

标签: c++ istream streambuf


【解决方案1】:

是否可以制作一个读取多个文件的istream

是的,但您必须自己制作。你可以通过扩展std::istream来实现自己的istream类,然后实现它定义的方法:

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

std::istream 的界面足够灵活,可以让您为所欲为。 然而,实现std::istream 需要大量工作,因为您必须实现整个接口。

有更简单的解决方案吗?

如果您只需要std::istream 提供的功能的子集,您可以编写自己的类。

例如,如果您只需要能够从文件中读取行,那么下面的类将适用于多个文件:

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; 
        }
    }
};  

【讨论】:

  • 实现自定义std::streambuf/std::filebuf 可能比实现自定义std:istream 更容易/更好。当流缓冲区在读取数据时遇到EOF,它可以简单地打开下一个文件并继续读取,istream 不会知道其中的区别。
  • 我一定会试试的,谢谢你们!有人知道streambuf接口的详细描述吗?
猜你喜欢
  • 1970-01-01
  • 2020-06-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-10
  • 1970-01-01
  • 2021-04-09
  • 1970-01-01
相关资源
最近更新 更多