Search code examples
c++vectorgetlineistream

How to write the content of different files to a vector for further use with getline


I want to save the content of different files to a vector: Vector(0) = Content File1 Vector(1) = Content File2 ...

Later on I need to read out from each index of this vector line by line (getline):

getline(Vector(0), string myString)

As I read on different sites, I can't use vector<istream> myVector.

So how can I solve?


Solution

  • It depends on the size of the data you want to manipulate. My two samples has been tested.

    You can use a class which handles some raw pointers

    #include <iostream>
    #include <fstream>
    #include <vector>
    #include <string>
    
    class file_vector 
    {
    public:
      file_vector()
      {}
    
      virtual ~file_vector()
      {
        for( std::vector< std::ifstream* >::iterator it = m_file_streams.begin(); it != m_file_streams.begin(); it++)
        {
          std::ifstream * p_stream = *it;
          delete p_stream;
        }
      }
    
      void append_file(const std::string& file_name)
      {
        std::ifstream * p_stream = new std::ifstream( file_name.c_str() );
        if(p_stream->is_open())
          m_file_streams.push_back(p_stream);
        else
          delete p_stream;
      }
    
      void reset()
      {
        for( std::vector< std::ifstream* >::iterator it = m_file_streams.begin(); it != m_file_streams.end(); it++)
        {
          std::ifstream * p_stream = *it;
          p_stream->seekg(0,p_stream->beg);
        }
      }
    
      size_t size()
      {
        return m_file_streams.size();
      }
    
      std::ifstream & get(size_t index)
      {
        return * m_file_streams.at(index); // Using at because of index check
      }
    
      std::ifstream & operator [] (size_t index)
      {
        return get(index);
      }
    
    private:
      std::vector< std::ifstream* > m_file_streams;
    };
    
    
    int main()
    {
      file_vector files_content;
      files_content.append_file("file1.txt");
      files_content.append_file("file2.txt");
      files_content.append_file("file3.txt");
    
      for(size_t i = 0; i < files_content.size(); i++)
      {
        std::string current_line;
        while(std::getline(files_content[i],current_line))
          std::cout << current_line << std::endl;
      }
    
      files_content.reset(); // To make getline usable again
    
    
      return 0;
    }
    

    Or a std::vector< std::vector< std::string > >. That's a basic solution for small files but it works.

    #include <iostream>
    #include <fstream>
    #include <vector>
    #include <string>
    
    typedef std::vector< std::string > string_vec;
    typedef std::vector< std::string >::iterator string_it;
    
    typedef std::vector< string_vec> file_vec;
    typedef std::vector< string_vec >::iterator file_it;
    
    int main()
    {
      string_vec file_names;
      file_names.push_back("file1.txt");
      file_names.push_back("file2.txt");
      file_names.push_back("file3.txt");
    
      file_vec files_content;
      string_vec empty_file_content;
    
      for(string_it file_name = file_names.begin(); file_name != file_names.end(); file_name++)
      {
        std::ifstream input_stream( file_name->c_str() );
        files_content.push_back(empty_file_content);
    
        if(input_stream.is_open())
        {
          string_vec & current_file_content = files_content[ files_content.size() - 1 ];
          std::string current_line;
          while(std::getline(input_stream, current_line))
            current_file_content.push_back(current_line);
        }
      }
    
      // Some stuff
    
        // Reading the content later on
      for(file_it file = files_content.begin(); file != files_content.end(); file++)
      {
        for(string_it line = file->begin(); line != file->end(); line++)
        {
          std::cout << *line << std::endl;
        }
      }
    
      return 0;
    }