-1

I'm trying to read data from binary file using folloing code:

fstream s;
s.open(L"E:\\test_bin.bin", ios::in | ios::binary);
int c = 0;
while (!s.eof())
{
    s >> c;
    cout << c;
}

c is always 0 (current value of c. If I set c to 1, result is 1). File exists and it has data that is not zeros, so problem is not at file. I can read this file using fread and using s.get(), but why given code not working?

Xanx
  • 545
  • 1
  • 5
  • 17
  • Place an if(s) after opening the file to detect an error (also `while (!s.eof())` is wrong) –  May 01 '14 at 08:27
  • What do you expect 'c' to contain after reading in from the binary file? A chunk of bits or a complete number? – ilent2 May 01 '14 at 08:29
  • It still read nothing, but as I mentioned file is ok and opens successfully. – Xanx May 01 '14 at 08:30
  • Chunk of bits, of course. – Xanx May 01 '14 at 08:30
  • possible duplicate of [Why is iostream::eof inside a loop condition considered wrong?](http://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong) – πάντα ῥεῖ May 01 '14 at 08:43

2 Answers2

1

Using the ios::binary flag doesn't necessarily mean that you read and write binary data. Take a look at https://stackoverflow.com/a/2225612/2372604 . ios::binary means "data is read or written without translating..."

What you probably want to do is use s.read(...). In your case the stream operator attempt to read a complete integer (something like "1234") rather then X number of bits that will fit into your integer.

For reading 4 bytes, something like the folling might work (untested):

int n;
while (s.read((char*) &n, 4) && s.gcount() != 0 ) {}
Community
  • 1
  • 1
ilent2
  • 5,171
  • 3
  • 21
  • 30
  • And I need to read complete 4 bytes. You mean that I cannot use >> to read bytes from file? – Xanx May 01 '14 at 08:35
  • 2
    "data is read or written without translating..." is the definition of *binary stream* – M.M May 01 '14 at 08:37
  • 1
    This is of course incorrect. The loop should be `while ( s.read((char*n)&n, 4) && s.gcount() != 0 ) {}`. Except that it would still just read raw bytes into the `int`, which is never right. – James Kanze May 01 '14 at 08:39
  • @JamesKanze Thanks, I was a bit too hasty. – ilent2 May 01 '14 at 08:41
  • @MattMcNabb No it doesn't. In particular, it will skip leading white space. – James Kanze May 01 '14 at 08:45
  • @MattMcNabb I'm fairly sure the `>>` overloads for `char` and `unsigned char` are formatted, i.e. a `sentry` object is created, and whitespace is skipped by default etc. – user657267 May 01 '14 at 08:45
  • 1
    @user657267 A `sentry` object is always created, even for `s.read`. The difference is that for `>>` (except if the target is a `streambuf*`), the sentry argument is initialized with the `skipws` flag from `ios_base`; with the non-formatted input, it is initialized with the constant `noskipws`, regardless of the state of the flag in `ios_base`. – James Kanze May 01 '14 at 08:48
1

What's wrong with:

int c = 0;
char ch;
int shift = 32;
while ( s.get( ch ) && shift != 0 ) {
    shift -= 8;
    c |= (ch & 0xFF) << shift;
}
if ( shift != 0 ) {
    //  Unexpected end of file...
}

This is the (more or less) standard way of reading binary 32 bit integers off the network. (This supposes that native int is 32 bits 2's complement, of course.)

Some protocols use different representation of 32 bit ints, and so will require different code.

As for your original code: the test s.eof() is always wrong, and >> is for inputting text; in particular, it will skip leading whitespace (and binary data may contain codes which correspond to whitespace).

I might also add that you should ensure that the stream is imbued with the "C" locale, so that no code translation occurs.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
  • Wouldn't that read the int in Big Endian format ? @James – lastbreath Feb 17 '21 at 15:09
  • 1
    In most network protocols, ints are big endian. It's pretty much a standard. (Rather surprising, in a way, since most of the early protocols were developed on DEC processors, which are little endian.) – James Kanze Feb 18 '21 at 20:05