1

Possible Duplicate:
Why failbit set when eof on read? Is there a way out?

I am writing a little program and it was working brilliantly on Mac OS and Ubuntu (Unix...). The program has to read in a data file and separate the bytes (chars / unsigned chars) and memcpy() them into floats. This would include the process of taking say the following four values, reading & left shifting them into a 32bit int and then copying the ints memory into a float. Like so:

0x43 0x66 0x1A 0x79 -> read in int32 and memcpy() into float -> val = 230.103

As I said, this works fine for Unix, but Windows seems to interpret the char 0x1A as an end of file (EOF) error and stop reading in data. Why does Windows do such a thing and not Unix? And how could I turn it off?

I even tried error handling by looking at the ifstream itself and check if the EOL flag has been set. Then I would clear() the ifstream's error flags and continue reading (using get()) but the damn thing always returns the same EOF / 0x1A character and does not read in the next character.

EDIT: Added some code


ifstream input (PATH, ios::in);
if (input.is_open()) {
  unsigned int counter = 0;
  while (input.good()) {
    BYTE byte;
    byte = input.get();
    printf("%i, ", byte);
    counter++;
  }
  printf("\r%i, ", counter);
  input.close();
} else {
  printf("Can't open file!");
}

Any help is very much appreciated.

Max

Community
  • 1
  • 1
Max Z.
  • 801
  • 1
  • 9
  • 25
  • Damn... the second I posted this a link became popped up in the Related section with a solution to the problem: http://stackoverflow.com/questions/6781545 Still, why does it work on Unix, but not Windows? – Max Z. Nov 27 '12 at 11:06
  • Max, you fail to show any code. How can we tell what you did wrong/should change? – sehe Nov 27 '12 at 11:06
  • 3
    You are using ios::binary ? – Alex K. Nov 27 '12 at 11:08
  • 2
    try to add the flag ios::binary when opening the file, to see if it help. – lucasg Nov 27 '12 at 11:09
  • @sehe: Yes there's sort of a duplicate a I stated in my 1st comment... A solution has been found, but no answer as to why Windows differs from Unix :P (Question may be closed if necessary...) – Max Z. Nov 27 '12 at 11:18
  • @MaxZ.: Windows is different because windows file API differentiates between binary and text files. On Unix, a file is a file is a file and the only difference between text and binary is how humans interpret them. – slebetman Nov 27 '12 at 11:45
  • @MaxZ. If you look at Unix in general, you'll see that Unix by design generalizes lots of things. For example a device on Unix is just a special kind of file so that devices can be managed by using the filesystem (on Win, devices are managed by a special program). Similarly, on Unix sockets, files and pipes are just types of file descriptors. On Unix a program is a program is a program and they all have stdin, stdout and stderr. Win differentiates between console and GUI programs such that GUI programs don't have stdin, stdout or stderr. There are many other examples of this trend. – slebetman Nov 27 '12 at 11:51
  • Voting to reopen/fix, as the "source" question was removed, thus this question needs another source. – Vesper Mar 11 '20 at 11:24

2 Answers2

7

With ifstream input (PATH, ios::in);, you open the file in (the default) text mode. When a file is opened in text mode, the standard library performs platform-specific conversions on the data read from the file to map the platform's native format for text files into the view that C (and C++) has of a text file.

For unix-like systems (including Mac OSX and Linux), the native text format is the same as how C and C++ view a text, so no conversions are needed.

On Windows platforms, the line-endings have to be converted ('\n' is converted to and from the character sequence CR LF), and the EOF character that Windows defines (1A) has to be interpreted.

On other systems, more extensive conversions might be needed (for example, if a text-file is specified as space-padded lines of exactly 80 characters, the implementation will have had to generate a '\n' character itself after reading 80 characters, and it might suppress the trailing space characters in a line).

Bart van Ingen Schenau
  • 15,488
  • 4
  • 32
  • 41
1

with ios::binary flag :

#include <iostream>
#include <fstream>
#include <windows.h>

int main()
{

    std::ifstream input ("msg.txt",  std::ios::binary );
    if (input.is_open())
    {
        unsigned int counter = 0;
        while (input.good()) 
        {
            BYTE byte;
            byte = input.get();
            printf("%d : %d \n", counter,  byte);
            counter++;
        }

        input.close();
    }
}

Input data : 0x43 0x66 0x1A 0x79 0x68 0xAc

output :

0 : 48 
1 : 120 
2 : 52 
3 : 51 
4 : 32 
5 : 48 
6 : 120 
7 : 54 
8 : 54 
9 : 32 
10 : 48 
11 : 120 
12 : 49 
13 : 65 
14 : 32 
15 : 48 
16 : 120 
17 : 55 
18 : 57 
19 : 32 
20 : 48 
21 : 120 
22 : 54 
23 : 56 
24 : 32 
25 : 48 
26 : 120 
27 : 65 
28 : 99 
29 : 32 
30 : 255

In this example the data is read char by char, but you can adapt it to your use case using ifstream.read(buffer, buffersize) .

By the way, this program was compiled with gcc on Windows7

lucasg
  • 10,734
  • 4
  • 35
  • 57