Reading Binary File

Hi Everyone!
I have the file "timelog.dat", which is a binary file with measure data from different sensors Called A, B, C etc and Each measure data is stored as a structure of the following appearance

1
2
3
4
5
strcut DataRecord{ 
      char logger; // Define logging Point A, B, C 
      double temp; // logged Temperature 
      time_t locTime; //Local Time
};


My program is reading this file and saving all data from the sensor A into the text file A.txt. The rest of data I am ignoring. which is almost achieved although I have couple of problems:

1. Rounding up temp(type double) to 1 decimal place
2. Displaying locTime format: "Sat Oct 10 15:50:15 2013"
3. Saving All the data to file A.txt.

Here is my Code: and so, for i am able to display it on the screen but can not store it into file "A.txt" according to 1 and 2

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
#include <iostream>
#include <fstream>
#include <ctime>
#include <cmath>
#include <iomanip>

using namespace std;

void readBinaryFile();
void writeTxtFile();

struct DataRecord{
    char logger;
    double temp;
    time_t locTime;
};

int main()
{
    DataRecord dRecord;
    readBinaryFile();
    return 0;
}

void readBinaryFile(){
    char logger;
    double temp;
    time_t locTime;

    fstream myReadFile;
    myReadFile.open("timelog.dat",ios::in | ios::binary);
    cout << "Data A" << endl;
    while(!myReadFile.eof()){
        myReadFile.read((char *)(&logger), sizeof(logger));
        if(logger == 'A'){
            myReadFile.read((char *)(&temp), sizeof(temp));
            cout << temp << ", " ;
            myReadFile.read((char *)(&locTime), sizeof(locTime));
            cout << locTime << endl;
        }
    }
}

void writeTxtFile(){
    fstream myWriteFile;
    myWriteFile.open("A.txt", ios::out);
    if(myWriteFile.is_open()){
         myWriteFile << "Write Data to File " <<endl;
    }
}


So far the output is: (output on Console)

Data A
2.452583-107, -171798692
1.1988e-256, 1030792151
.
.
.
and so on

Whereas I want it in the following: (output into file "A.txt")
Data A
2.4, Sat Oct 06 15:30:15 2013
1.1 Fri Oct 10 10:14:01 2013
.
.
.
and so on

Thanks in advance

Sincere Regards!
Last edited on
Hi BitRat !

I tried these both statements but it changes the values to something very different

1
2
printf("%f", temp);
cout<<fixed<<setprecision(1)<<temp; 


with
cout<<setprecision(1) << temp<<endl;

I get an output of
2e-107
1e-256
.
.
.
and so on

and With the
cout<<fixed<<setprecision(1)<<temp<<endl;
I get an output of
0
0
7333332343234234234234234234234234234234234234234 -134234234234234234234234234234234234234234234234923942345
-0
0
1038393023423423424923042934023942034
.
.
and so on

any idea what the problem is?
Last edited on
Time doesn't work either

here is my code

1
2
3
4
5
myReadFile.read((char *)(&locTime), sizeof(locTime));
struct tm * timeinfo;
time (&locTime);
timeinfo = localtime((&locTime));
printf("%s", asctime(timeinfo));


it prints the current time but not the time stamp from the dat file :(
Are you sure that you are reading the data file correctly?

I see several possible issues.
1
2
3
4
5
6
7
8
9
    while(!myReadFile.eof()){
        myReadFile.read((char *)(&logger), sizeof(logger));
        if(logger == 'A'){
            myReadFile.read((char *)(&temp), sizeof(temp));
            cout << temp << ", " ;
            myReadFile.read((char *)(&locTime), sizeof(locTime));
            cout << locTime << endl;
        }
    }

First, the eof() test not a good idea. Your code should perform a read operation, and only proceed to do something with the result if the read was successful. At the very least, the eof() test is too late, as it always testing what happened last time, but cannot predict what will happen within the body of the loop when the next read is attempted.

Another issue is that the logger value is read from the file, and only if it contains the letter 'A' is the remainder of the data read. That means as soon as a non-'A' record is encountered, the reading will get out of synchronisation. I believe you should always read all of the items of that record, in order that the next time around, the file position will be at the start of the next record.

And finally there is the issue of padding and alignment. I don't know how the data was originally written to the data file. If the entire structure DataRecord was written as a single block of bytes, there may be some padding, in order to ensure that the numeric items are located at the correct memory boundary, say a multiple of 2, 4 or 8 bytes depending on type of item.

When I tried to create a sample file on my system, each data record occupied anywhere from 13 to 24 bytes, depending upon this padding.

Once you have got the input fixed (see Chervil's post above), the rest is a walk in the park:

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
#include <iostream>
#include <ctime>
#include <iomanip>

int main()
{
    // read in logger, temperature, timestamp
    char logger = 'A' ;
    double temperature = 2.452583 ;
    std::time_t timestamp = 1381201786 ;

    if( logger == 'A' )
    {
        std::cout << "Data A\n" ;

        // 1. Rounding up temp(type double) to 1 decimal place
        std::cout << std::fixed << std::setprecision(1) << temperature << ", " ;

        // 2. Displaying locTime format: "Sat Oct 10 15:50:15 2013"
        char cstr_time[1024] ;
        std::strftime( cstr_time, sizeof(cstr_time), "%a %b %d %H:%M:%S %Y\n",
                        std::localtime( &timestamp ) ) ;
        std::cout << cstr_time ;
    }
}

http://coliru.stacked-crooked.com/
Topic archived. No new replies allowed.