Issue in reading a binary file

Hi guys i have a problem while reading a binary file... I have written some data in binary format and want to read the data now... but when i print the data its coming a null ... ppls help me out
My code is as follows

BinaryIO,h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <string>
#include <list>
#include <fstream>

using namespace std;

class BinaryIO
{
        private:
                char* data;

        public:
                void readBinFile(string);
                void writeBinFile(string,list<unsigned long>,ofstream&);
                BinaryIO(size_t);
                BinaryIO();
};


BinaryIO.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include <iostream>
#include <fstream>
#include <string>
#include <sys/stat.h>
#include <list>
#include "BinaryIO.h"

using namespace std;

BinaryIO :: BinaryIO(size_t sz)
{
        data = new char[sz];
        cout<<sizeof(data);
}

BinaryIO :: BinaryIO()
{
        data =new char [20];

}

void BinaryIO :: readBinFile(string sPath)
{
        ifstream file (sPath.c_str(), ios::in|ios::binary|ios::ate);
        ifstream::pos_type size;
        if(file.is_open())
        {
                size = file.tellg();
                cout<<"SIZE "<<size<<endl;
                BinaryIO ReadData(size);
                file.seekg(0,ios::beg);
                file.read(reinterpret_cast<char *>(&ReadData),sizeof(BinaryIO));
                file.close();
                cout<<"READING FILE: "<<data<<endl;
        }

}

void BinaryIO :: writeBinFile(string filePath,list <unsigned long> writeData,ofstream& file)
{
        struct stat buffer;
        BinaryIO binWriteData;
        ifstream::pos_type size;
        int status;
        list <unsigned long> :: iterator itr;
        size = file.tellp();

        for(itr = writeData.begin();itr != writeData.end();itr++)
        {
                sprintf(data,"%lu",*itr);
                memset(data,' ',20);
                file.write(reinterpret_cast<char *>(&binWriteData),sizeof(BinaryIO));
        }
}


test.cpp
1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
#include "BinaryIO.h"

using namespace std;

int main()
{
        BinaryIO binReadData;
        binReadData.readBinFile("a-o.idx");
        return 0;
}


Pls help me out here
-Herat
Last edited on
cout<<sizeof(data);
will always return 4. sizeof() is compile time operator so will always return the wrong value.

file.read(reinterpret_cast<char *>(&ReadData),sizeof(BinaryIO));
this will always read 4 bytes as the size of class will be 4 always on 32bit.
do it simple. Also, if you want to read only characters from binary file it will work fine but for numbers, double or floats etc you need to join the bytes to form a full value and only then you can print it.

I think first you need to read the file correctly.
like:
file.read(&data,<Some value>);


Last edited on
I managed to solve that issue .. it was an error in one line where i was doing << operation for the binary file.. we should not do that ..
But now I have one more issue... Can we write a string or a char* into a binary file.. and then read the same....
My code for write is
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
void BinaryIO :: writeDictBinFile(string filePath,string sTermValues,ofstream& file)
{
        string sTempStr1,sTempStr2,sTempStr3;
        //const char* tempToken= sTermValues.c_str();
        vector<string> tempVector;
        //stringstream ss(sTermValues);
        cout<<"writeDictBinFile"<<endl;
        int len = sTermValues.length();
        cout<<"Length"<<len<<endl;
        TermDictData td_data;
        char *sb = new char[len+1];
        char *sToken = new char [len+1];
        strcpy(sb,sTermValues.c_str());
        char *pch;
        pch = strtok(sb,"|");
        while (pch != NULL)
        {
                cout<<"Inwhile"<<endl;
                tempVector.push_back((string)pch);
                cout<<"After Push back "<<pch<<endl;
                char* pch2;

                pch = strtok (NULL, "|");
        }

        sToken = strcpy(sToken,tempVector[0].c_str());
        int len2 = strlen(sToken);
        cout<<"Len2 "<<len2;
        td_data.termId = strtoul(tempVector[1].c_str(),NULL,0);
        td_data.docFreq = strtoul(tempVector[2].c_str(),NULL,0);
        cout<<sToken<<endl<<td_data.termId<<endl<<td_data.docFreq<<endl;
        file.write(reinterpret_cast<char *>(&len),sizeof(int));
        file.write(reinterpret_cast<char *>(&sToken),len);
        file.write(reinterpret_cast<char *>(&td_data),sizeof(TermDictData));
        cout<<"-------------------------------------------------"<<endl;

}




and that for read is
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void BinaryIO :: readDictBinFile(string sPath)
{
        ifstream file (sPath.c_str(), ios::binary|ios::in);
        char *sToken;
        TermDictData td_data;
        int iTokenLen;
        if(file.is_open())
        {
                while(!file.eof())
                {       cout<<"Inwhile"<<endl;
                        file.read(reinterpret_cast<char *>(&iTokenLen),sizeof(int));
                        cout<<"I TOKEN LEN"<<iTokenLen<<endl;
                        sToken = new char[iTokenLen+1];
                        file.read(reinterpret_cast<char *>(&sToken),iTokenLen);
                        file.read(reinterpret_cast<char *>(&td_data),sizeof(TermDictData));
                        cout<<"After read"<<endl;
                        cout<<iTokenLen<<endl<<sToken<<endl<<td_data.termId<<endl<<td_data.docFreq<<endl;
                }
                file.close();
        }

}


Now can we do the part which is in bold.. it is not working for me
I managed to solve that issue .. it was an error in one line where i was doing << operation for the binary file.. we should not do that ..
But now I have one more issue... Can we write a string or a char* into a binary file.. and then read the same....
My code for write is
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
void BinaryIO :: writeDictBinFile(string filePath,string sTermValues,ofstream& file)
{
        string sTempStr1,sTempStr2,sTempStr3;
        //const char* tempToken= sTermValues.c_str();
        vector<string> tempVector;
        //stringstream ss(sTermValues);
        cout<<"writeDictBinFile"<<endl;
        int len = sTermValues.length();
        cout<<"Length"<<len<<endl;
        TermDictData td_data;
        char *sb = new char[len+1];
        char *sToken = new char [len+1];
        strcpy(sb,sTermValues.c_str());
        char *pch;
        pch = strtok(sb,"|");
        while (pch != NULL)
        {
                cout<<"Inwhile"<<endl;
                tempVector.push_back((string)pch);
                cout<<"After Push back "<<pch<<endl;
                char* pch2;

                pch = strtok (NULL, "|");
        }

        sToken = strcpy(sToken,tempVector[0].c_str());
        int len2 = strlen(sToken);
        cout<<"Len2 "<<len2;
        td_data.termId = strtoul(tempVector[1].c_str(),NULL,0);
        td_data.docFreq = strtoul(tempVector[2].c_str(),NULL,0);
        cout<<sToken<<endl<<td_data.termId<<endl<<td_data.docFreq<<endl;
        file.write(reinterpret_cast<char *>(&len),sizeof(int));
        file.write(reinterpret_cast<char *>(&sToken),len);
        file.write(reinterpret_cast<char *>(&td_data),sizeof(TermDictData));
        cout<<"-------------------------------------------------"<<endl;

}




and that for read is
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void BinaryIO :: readDictBinFile(string sPath)
{
        ifstream file (sPath.c_str(), ios::binary|ios::in);
        char *sToken;
        TermDictData td_data;
        int iTokenLen;
        if(file.is_open())
        {
                while(!file.eof())
                {       cout<<"Inwhile"<<endl;
                        file.read(reinterpret_cast<char *>(&iTokenLen),sizeof(int));
                        cout<<"I TOKEN LEN"<<iTokenLen<<endl;
                        sToken = new char[iTokenLen+1];
                        file.read(reinterpret_cast<char *>(&sToken),iTokenLen);
                        file.read(reinterpret_cast<char *>(&td_data),sizeof(TermDictData));
                        cout<<"After read"<<endl;
                        cout<<iTokenLen<<endl<<sToken<<endl<<td_data.termId<<endl<<td_data.docFreq<<endl;
                }
                file.close();
        }

}


Now can we do the part which is in bold.. it is not working for me it gives me a segmentation fault while printing sToken in readDictBin.. It writes into a binary file properly.....

Pls Help me Out
Herat
Last edited on
file.read(sToken,iTokenLen);

will work. no need to type cast or send the address.
I noticed if we do it this way then the word directly inserts itself in a human readable format
here is a snippet of what it looks like

^N^@^@^@abandon^@<90>mV
^@^@ª^C^@^@^@^@^@^@^A^@^@^@^@^@^@^@^K^@^@^@abil^@^@^@^@ mVi^B^@^@^@^@^@^@^B^@^@^@^@^@^@^@

Check out the bolded words.... Is it proper or they should be in binary format and not in human readable format

Thanks
Herat
if you have only characters in the file it will read and display fine. but if you have multi-byte values like numbers, unicode then you have more work to do. what kind of file is this?
characters will be readable even if they are binary so dont worry about them.
this file contains characters as well as nos...... so i can c nos as binary format but characters as human readable format.... pls correct me if i m wrong... what i have understood is that .. since characters are 1 byte and we are writing it in binary format so it doesnt matter whether we write it in binary format or text format the size for characters will be the same... hence c++ doesnt allow characters or strings to be type casted and the stored when reading from binary file....

Thanks for the help...
exactly...you got it correct.

you dont have to do anything for characters but for numbers you have join them and for that you should be knowing if they are 2 bytes or 4 or these days can be 8 also..
int num = (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4; //for 4 bytes, its something like this
so read characters normally and print them but when you encounter numbers join them like this way:

easiest way will be write numbers at fixed byte length and then read these bytes directly in int or long and you will get it correct.
Last edited on
Topic archived. No new replies allowed.