Nikolas Jíša
Nikolas Jíša

Reputation: 709

Reading byte from file to an array variable C++

This is my follow up question to this question

When I try this:

int main ( void ) {
fstream F ( soubor1, ios::out | ios::binary );
unsigned int x = 0xc4;
F.write ( ( char * ) &x, 1 );
x = 0x8d;
F.write ( ( char * ) &x, 1 );
F.close();
F . open ( soubor1, ios::in | ios::binary );
while ( F. read ( (char * ) & x, 1) )
cout << x << " ";
return 0;}

It works how I d suppose it would work... But when I do this:

int main ( void ) {
    fstream F ( soubor1, ios::out | ios::binary );
    unsigned int x = 0xc4;
    F.write ( ( char * ) &x, 1 );
    x = 0x8d;
    F.write ( ( char * ) &x, 1 );
    F.close();
    F . open ( soubor1, ios::in | ios::binary );
    unsigned int a[2]; //or unsigned int * a = new unsigned int[2];
    while ( F. read ( (char * ) & a[0], 1) )
    cout << a[0] << " ";
    return 0;}

.. so it doesnt print "196 141" ... but some crazy numbers...

Thanks in advance,

Nikolas Jíša

Upvotes: 0

Views: 1027

Answers (3)

Sylvain Defresne
Sylvain Defresne

Reputation: 44503

This is because sizeof(char) == 1 and sizeof(int) == 4. The std::ostream::write(const char*, size_t) function interpret its last argument as the number of bytes to write. So when you write, you only write 2 bytes. The std::istream::read(char*, size_t) function also interpret its last argument as a number of bytes to read.

So, using some diagram to represent you code, we have:

fstream F ( soubor1, ios::out | ios::binary );
unsigned int x = 0xc4;

// x =
// ,---------------------------.
// | 0xc4 | 0x00 | 0x00 | 0x00 |
// `---------------------------'

F.write((const char*)&x, 1);

// This write the first byte of x into the file,
// that is it write the byte 0xc4

x = 0x8d;


// x =
// ,---------------------------.
// | 0x8d | 0x00 | 0x00 | 0x00 |
// `---------------------------'

F.write((const char*)&x, 1);

// This write the first byte of x into the file,
// that is it write the byte 0x8d

F.close();
F.open( soubor1, ios::in | ios::binary );

unsigned int a[2];

// a =
// ,-------------------------------------------------------.
// |  ??  |  ??  |  ??  |  ??  |  ??  |  ??  |  ??  |  ??  |
// `-------------------------------------------------------'

F.read((char*)&a[0], 2);

// a =
// ,-------------------------------------------------------.
// | 0xc4 | 0x8d |  ??  |  ??  |  ??  |  ??  |  ??  |  ??  |
// `-------------------------------------------------------'

// You just read two bytes, while a point to a region that is
// 8 bytes long. So only the first two bytes of the first int
// are initialized, all the other value are undefined.

You can correct your code this way:

int main () {
    fstream F ( soubor1, ios::out | ios::binary );
    unsigned int x = 0xc4;
    F.write ( ( char * ) &x, sizeof(unsigned int) );
    x = 0x8d;
    F.write ( ( char * ) &x, sizeof(unsigned int) );
    F.close();
    F.open ( soubor1, ios::in | ios::binary );
    unsigned a[2];
    F.read((char*)a, 2 * sizeof(unsigned int));
    for (size_t i = 0; i < 2; ++ i)
        cout << a[i] << " ";
    return 0;
}

Upvotes: 1

Fred Foo
Fred Foo

Reputation: 363627

a[0] is not initialized before the read, so the value is garbage. You then read a char into the first byte of a[0], so that gets a proper value, but the rest of it doesn't.

You should be using char's instead of int's, since int's are typically larger (they commonly occupy a size of 4 or 8 times that of char, on modern platforms).

Contrary to what you might think, setting a[0] to 0 before the read won't help either, at least not portably, because of endianness issues.

Upvotes: 2

Jon
Jon

Reputation: 437424

You are reading into an array of ints, which (probably) are 4 bytes long.

The read call reads just one byte, which is the first of the 4 bytes of the first int in the array. Since the array is not initialized first, when you do cout << a[0] what happens is that it prints out an int whose value is produced by the one byte you just read and the 3 other bytes that were already there. Clearly this will not result in the values you expect.

You should change unsigned int a[2] to unsigned char a[2], and then it will work.

Upvotes: 0

Related Questions