Search code examples
c++binaryfstream

C++ fstream - can't read from file using binary format


I'm now trying to write some integer values to file and then read it using fstream. Here is how i'm doing it:

#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <string>           

typedef unsigned char  BYTE; // 1byte
typedef unsigned short  WORD; // 2bytes
typedef unsigned long  DWORD; //4bytes

using namespace std;

template <typename Word>
ostream& write_word( ostream& outs, Word value )
{
    for (unsigned size = sizeof( Word ); size; --size, value >>= 8)
        outs.put( static_cast <char> (value & 0xFF) );
    return outs;
}

template <typename Word>
istream& read_word( istream& ins, Word& value )
{
    for (unsigned size = 0, value = 0; size < sizeof( Word ); size++)
            value |= ins.get() << (8 * size);   
    return ins;
}   


int main()
{            
    system("CLS");
    int num = 1;                 
    string *str;

    cout<<"How much strings do you want to write: ";
    cin>>num;

    if(num <= 0)
    {                       
        cout<<"\nInvalid value!"<<endl;
        return 1;                
    }

    str = new string[num];

    ofstream out("2.txt",ios::binary|ios::out);

    for(int i = 0; i< num; i++){
        cout<<"Insert string";
        cout<<i;      
        cout<<": ";
        cin>>str[i];

        write_word(out, (DWORD)str[i].length());
        out<<str[i];

    }                               

    out.close();
    cout<<"Values saved to 2.txt."<<endl;

    for(int i = 0; i< num; i++){
        cout<<"string"<<i<<" = "<<str[i]<<endl; 
    }

    system("PAUSE");

    cout<<"Loading values from 2.txt now."<<endl;

    ifstream in("2.txt",ios::binary|ios::in);

    if(!in.is_open()){ cout<<"ERROR"; return 1; }

    for(int i = 0; i< num; i++){
        DWORD len = 0x0;
        read_word(in, len);

        cout<<"string"<<i<<" length is "<<len<<endl;

        char *tmpStr = new char[len];
        in.read(tmpStr, len);
        std::string str2(tmpStr, len);

        cout<<"string"<<i<<" = "<<str2<<endl;
    }

    in.close();    
    system("PAUSE");        

    return 0;
}

Writing succeeds so i can see changes in the file but i can't figure out why reading string sizes from it doesn't work. String sizes is always zero and resulting strings are empty.


Solution

  • for (unsigned size = 0, value = 0; size < sizeof( Word ); size++) declares a new value inside the loop scope.

    By refering to value, you are changing unsigned value declared in the loop, not the parameter. Set the value to zero before the loop. It's also easier to read and understand.

    The final code:

    template <typename Word>
    istream& read_word( istream& ins, Word& value )
    {
        value = 0;
        for (unsigned size = 0; size < sizeof( Word ); size++)
                value |= ins.get() << (8 * size);   
        return ins;
    }