Byte reading problems!!

When writing bytes, the last numbers last byte value is 10. When reading, it appears that its value is 13 ! How could it be like this?! All the evidence occurs when running the program.

My code:
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include <iostream>
#include <fstream>
#include <string>

using namespace std;

void longToBytes(long num, unsigned char arr[4])
{
    arr[0]= (int)((num >> 24) & 0xFF);
    arr[1]= (int)((num >> 16) & 0xFF);
    arr[2]= (int)((num >> 8) & 0xFF);
    arr[3]= (int)( num & 0xFF);
}

long bytesToLong(unsigned char arr[4])
{
    return ((arr[0] << 24) + (arr[1] << 16) + (arr[2] << 8) + arr[3]);
}

void writelongs(long mas[], int howMany)
{
    ofstream outp("data.txt");

    outp<<howMany<<" ";

    cout<<"Writing. \n\n";

    for(int i=0; i<howMany; i++)
    {
        unsigned char bytes[4];

        cout<<"The Number: "<<mas[i]<<"\nBytes as unsigned chars: ";

        longToBytes(mas[i], bytes);

        char by2[4];

        for(int j=0; j<4; j++)
        {
            cout<<(int)bytes[j]<<" ";
            //outp<<bytes[j];

            by2[j]=(char)bytes[j];
        }
        cout<<"\nBytes as chars: ";
        for(int j=0; j<4; j++)
        {
            cout<<(int)by2[j]<<" ";
        }
        outp.write(by2,4);

        cout<<"\n\n";
    }

    outp<<" ";

    outp.close();
}

int main()
{
    long aray[2]={-118, 1034}; //long array, which will be converted into bytes.

    writelongs(aray,2);

    ifstream inp("data.txt");

    int n;
    inp>>n;

    cout<<"---------------------\nReading.\n\nHow many nums: "<<n<<endl;

    long pos = inp.tellg();

    inp.close();

    FILE * f;
    f=fopen("data.txt","rb");

    fseek(f,pos,SEEK_SET);

    cout<<endl;

    for(int j=0; j<n; j++)
    {
        char b[4];
        fread(b,1,4,f);

        unsigned char a[4];

        cout<<"Bytes: ";
        for(int i=0; i<4; i++)
        {
            a[i]=(unsigned char)b[i];
            cout<<(int)a[i]<<" ";  //Here it is 13 !
        }
        cout<<endl;

        long num=bytesToLong(a);

        cout<<"Converted long: "<<num<<endl;

        if(num==aray[j]) cout<<"TRUE !\n\n";
        else cout<<"FALSE !\n\n";
    }

    fclose(f);

    return 0;
}


(Code updated!)
Last edited on
How do you know that it should be 10? What evidence do you have to support this claim?
Try to run the new code, it shows everything.

Tried opening ofstream in std::ofstream::binary mode, but it was even worse - when read, byte values were totally different.
Last edited on
binary mode is correct and is 100% necessary when writing binary data.. Without it, your output will be mangled by newline transformations.


Your other problem is that you are not properly reading back what you are writing. This is tricky because you are mixing textual output and binary output. I recommend not doing that -- pick one or the other and run with it.

Note: if you do not have a hex editor... get one. They are a godsend for when you're working with binary files. HxD is a fantastic free hex editor.

Assuming you change the code to output binary data... if you look at the generated file in a hex editor, you get this:

 
32 20 FF FF FF 8A 00 00 04 0A 20


The first '32' is your value of '2' stored as text. (0x32 == '2')
The '20' is the space (0x20 == ' ')
The 'FF FF FF 8A' is your -118 stored correctly in binary (though big endian? ew)
The '00 00 04 0A' is your 1034 stored in binary
And the final '20' is another space


The problem is your tellg() call on line 73 is sort of lying to you and returning 0 because... well... I'm not sure why. Probably because it's meant to be used with binary files and not with text files.

So anyway, when you open the file again with fopen() on line 78, you seek to position 0 on line 80... not to position 2 like you would need to in order for this to work properly.


The end result is that you are reading the 2 and space as part of your first number, which throws the whole thing off.
Last edited on
You cannot get or set the read/write cursor in text mode, so tellg returning 0 is expected undefined behavior.
It's not just text mode though. If you open in binary mode, then read with the >> operator, it still returns zero (at least for me). So it must have something to do with the buffered text parsing.

Regardless, it just drives home my main point: don't mix text and binary. Pick one and run with it.
Thanks! Full binary operating and casting combined works!!

My new, FULLY WORKING code:

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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#include <iostream>
#include <fstream>
#include <string>

using namespace std;

void longToBytes(long num, unsigned char arr[4])
{
    arr[0]= (int)((num >> 24) & 0xFF);
    arr[1]= (int)((num >> 16) & 0xFF);
    arr[2]= (int)((num >> 8) & 0xFF);
    arr[3]= (int)( num & 0xFF);
}

void longToChars(long num, char arr[4])
{
    arr[0]= (int)((num >> 24) & 0xFF);
    arr[1]= (int)((num >> 16) & 0xFF);
    arr[2]= (int)((num >> 8) & 0xFF);
    arr[3]= (int)( num & 0xFF);
}

long bytesToLong(unsigned char arr[4])
{
    return ((arr[0] << 24) + (arr[1] << 16) + (arr[2] << 8) + arr[3]);
}

string uncharToStr(unsigned char arr[], int hm)
{
    char chr[hm];

    cout<<"\nBytes as chars: ";
    for(int i=0; i<hm; i++)
    {
        chr[i]=(char)arr[i];

        cout<<(int)chr[i]<<" ";
    }
    cout<<"\n";

    string str(chr);

    return str;
}

void writelongs(long mas[], int howMany)
{
    ofstream outp("data.txt", std::ofstream::binary);

    if(!outp) return;

    char hmc[4];
    longToChars((long)howMany, hmc);

    outp.write(hmc,4);

    cout<<"HowMany: "<<howMany<<"\n\n";

    for(int i=0; i<howMany; i++)
    {
        char bytes[4];

        longToChars(mas[i],bytes);

        cout<<"Your "<<i<<" number: "<<mas[i]<<"\nBytes: ";
        for(int j=0; j<4; j++)
        {
            cout<<(int)(static_cast<unsigned char>(bytes[j]))<<" ";
        }
        cout<<"\n\n";

        outp.write(bytes,4);
    }

    outp.close();
}

int main()
{
    long aray[2]={-11854, 11111}; //long array, which will be converted into bytes.

    writelongs(aray,2);

    ifstream inp("data.txt", std::ifstream::binary);

    if(!inp) return -1;

    char hm[4];

    inp.read(hm,4);

    long sz=bytesToLong(reinterpret_cast<unsigned char*>(hm));

    cout<<"\n----------------------\nReading\n\n";
    cout<<"HowMany read: "<<sz<<endl;

    for(int i=0; i<sz; i++)
    {
        char bytes[4];

        inp.read(bytes,4);

        long num=bytesToLong(reinterpret_cast<unsigned char*>(bytes));

        cout<<"\nBytes: ";
        for(int j=0; j<4; j++)
        {
            cout<<(int)(static_cast<unsigned char>(bytes[j]))<<" ";
        }
        cout<<"\nConverted long: "<<num<<"\n";

        if(num==aray[i]) cout<<"TRUE !\n\n";
        else cout<<"FALSE !\n\n";
    }

    inp.close();

    return 0;
}
Topic archived. No new replies allowed.