Search code examples
c++fstreamifstreamofstream

Is there an elegant way to read a binary file and copy its content to a vector<int>


I tried this method:

void read(vector<int> &vec, string filename)
{
    std::ifstream file(filename, std::ios::binary | std::fstream::binary);
    if (!file.is_open()) throw runtime_error("could not open file");
    //std::istreambuf_iterator<char> start(file), end;
    std::istream_iterator<int> start(file), end;
    //std::istreambuf_iterator<char> start(file), end;
    vec = vector<int>(start, end);
    file.close();
}
void write(vector<int> &vec, string filename) {
    std::ofstream file(filename, std::ios::binary | std::fstream::binary);
    if (!file.is_open()) throw runtime_error("could not open file");
    copy(
        vec.begin(),
        vec.end(),
        //std::ostreambuf_iterator<char>(file)
        std::ostream_iterator<int>(file)
    );
    file.close();
}
int main(){
    vector<int> vec =
    {124,5,543,6,756,6,3,234,5,5,765}, vec2;
    write(vec, "thing.bin");
    read(vec2, "thing.bin");
    for (auto&a : vec2) cout << a << endl;
    system("PAUSE");
}

The commented code are alternative iterators I tried.

The problem is that std::ostreambuf_iterator<int>(file) is an invalid iterator to a file. Do I need to do a reinterpret_cast? Am I obligated to use fstream .write() and read() ?


Solution

  • void read(vector<int> &vec, string filename)
    {
        std::ifstream file(filename, std::ios::binary | std::fstream::binary);
        if (!file.is_open()) throw runtime_error("could not open file");
    
        file.seekg(0, ios_base::end);
        int size = file.tellg() / sizeof(int);
        vec = vector<int>(size);
        file.seekg(0, file.beg);
        file.read(reinterpret_cast<char*>(vec.data()), size*sizeof(int));
        file.close();
    }
    void write(vector<int> &vec, string filename) {
        std::ofstream file(filename, std::ios::binary | std::fstream::binary);
        if (!file.is_open()) throw runtime_error("could not open file");
        file.write(reinterpret_cast<const char*>(vec.data()), vec.size() * sizeof(int));
        file.close();
    }
    int main(){
        vector<int> vec =
        {0,1,2,3,-1,127,128,1023,1024}, vec2;
        write(vec, "thing.bin");
        read(vec2, "thing.bin");
        for (auto&a : vec2) cout << a << endl;
        return 0;
    }