1

The problem of reading (with c++ program) binary file generated by fortran code has been asked many times and the satisfactory description of conventions in fortran records has been given (e.g. http://local.wasp.uwa.edu.au/~pbourke/dataformats/fortran/ )

However when I try to implement c++ program, keeping in mind fortran conventions it still does not work. Here I assume we that the binary file "test.bin" contains 1 integer and is written in binary format by fortran routines. Here is how I try to read it in c++:

#include <iostream>
#include <fstream>
using namespace std;

int main () {
  ifstream file;
  file.open("test.bin", ios::in|ios::binary);
  if (file.is_open())
  {
    int ival;
    file >> ival >> ival;  cout<< ival<<endl;
   }
   return 0;
}

Here the double >>ival construction first reads the header of the fortran record (which contains the size of the record in bytes) and the second >>ival supposed to extract the value. The integer written in file is 8, but the program outputs 0, so it does not read the data properly.

Here is a content of the binary file: ^D^@^@^@^@^@^@^@^H^@^@^@^D^@^@^@^@^@^@^@

So my question - what am I doing wrong?

Here is what hex editor shows:

0000000: 0400 0000 0000 0000 0800 0000 0400 0000  ................
0000010: 0000 0000 0a                             .....

Any idea what that means?

Robᵩ
  • 163,533
  • 20
  • 239
  • 308
user938720
  • 271
  • 3
  • 14
  • 1
    HEX! Outputting the bytes as characters is not helping any. – Martin James Apr 17 '12 at 19:23
  • 1
    figure out if it is big endian or little endian. Intel is little endian. `^@ = 0, ^D = 4, ^H = 8`. Looks to me like little endian, record size is 4, value is 8. I do not know what the last 8 bytes are. – JimR Apr 17 '12 at 19:39
  • 2
    The `>>` operator reads textual data (i.e., it tries to parse an decimal representation of an integer). Use the `read` member function to read binary data. – Philipp Apr 17 '12 at 19:47
  • Well, the second integer, assuming 32-bit little-endian, is actually 0, next 8 and then 4. If the first integer written in the file is actually 8, it may be that the size header is a 64-bit integer - quite reasonable with large disk files. – Martin James Apr 17 '12 at 21:58

2 Answers2

2

operator>> is the formatted input operator. It is used to read text files, converting the textual representation to binary.

You should be reading using unformatted input operations. Try this:

file.read(reinterpret_cast<char*>(&ival), sizeof ival);

Of course, after you read it, you may need to byte swap for correct endian representation.

Robᵩ
  • 163,533
  • 20
  • 239
  • 308
  • I also tried another method: I first read entire content of the file in char buffer memoryblock, then i copy some elements of the memorymlock into temporary buffer buff (e.g. 4 elements) and the try: ival = atoi(buff). This still gives me 0, although I do not use >> operator (read function for binary input). Why is it not working? – user938720 Apr 17 '12 at 20:16
  • 1
    It isn't working because you use `atoi` -- a function which converts text to binary. You don't have text, you already have binary. There is no need to convert it. If you have read the file into a buffer, try this: `memcpy((void*)&ival, &memoryblock[0], sizeof ival)`. – Robᵩ Apr 17 '12 at 20:22
1

Open it in a hex editor and dig out the structure. Is the header size 16, 32, 64 or 128 bits and which end up is it?

Hex editor..

Martin James
  • 24,453
  • 3
  • 36
  • 60
  • As I understand, the header should be 4 bytes (see the reference/link I give), that is why I use first >>ival operation. Also: the file is in Linux - is there any Linux hex editors? Is it possible to copy that file to windows and use hex editor for windows? – user938720 Apr 17 '12 at 19:36
  • In many Linux distributions, you can display a file in hex like this: `od -txCz filename`. – Robᵩ Apr 17 '12 at 20:20