Writing and Reading Binary data in FORTRAN and C++
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 16

Thread: Writing and Reading Binary data in FORTRAN and C++

  1. #1
    Join Date
    Apr 2013
    Posts
    6

    Question Writing and Reading Binary data in FORTRAN and C++

    I am writing a double number in Binary format to the console of program A (in FORTRAN) with the following code:

    Code:
    REAL*8 A
    A = 12.54
    INQUIRE(6, name = xstring)
    OPEN(1,file=xstring, access='stream',action='write') 
    WRITE (1) A            
    CLOSE(1)
    And trying to read that number by program B (in C++) which is connected to program A by anonymous pipes. Following is the reading part of program B:

    Code:
    #define BUF_SIZE 5000 
    BOOL bSuccess = FALSE;
    char Buf[BUF_SIZE];
    DWORD dwRead;
    for (;;) 
    { 
      bSuccess = ReadFile( V_hChildStd_OUT_Rd, Buf, BUF_SIZE, &dwRead, NULL);
      if( ! bSuccess || dwRead == 0 )   break; 
    }
    Note: V_hChildStd_OUT_Rd is a handle to the output of program A.

    After running the program although bSuccess becomes TRUE, Buf array does not include the number (12.54) that I am expecting. If I do the same process without using the binary format it works fine and I can read the number. I know somethings wrong with the writing or reading of binary data but I do not know what it is.

    I would appreciate if someone can help me. Thanks!

  2. #2
    Join Date
    Apr 1999
    Posts
    27,427

    Re: Writing and Reading Binary data in FORTRAN and C++

    Quote Originally Posted by Vectorprg View Post
    I am writing a double number in Binary format
    What is "Binary format"?

    In C++, for most compilers, the format is usually an IEEE 64-bit floating point number, but nothing stops a compiler from implementing floating point numbers using a different scheme. So you need to know exactly what is this "binary format".

    Regards,

    Paul McKenzie

  3. #3
    Join Date
    Apr 2013
    Posts
    6

    Re: Writing and Reading Binary data in FORTRAN and C++

    As you know there are two formats: ASCII format (which is readable by human) and Binary format (which is computer language). I am now working with ASCII format which means I write the actual number (12.54) on the console and read that from it. To make the process faster I want to use binary format. It should write the binary representative of number 12.54 ( which appears as bunch of signs on the console) and then read it. But for some reason it is not working in binary format.

  4. #4
    Join Date
    Apr 1999
    Posts
    27,427

    Re: Writing and Reading Binary data in FORTRAN and C++

    Quote Originally Posted by Vectorprg View Post
    As you know there are two formats: ASCII format (which is readable by human) and Binary format (which is computer language).
    There are many different floating point formats. I even mentioned to you the IEEE format. You still failed to mention the exact format used by your Fortran program.

    There is no such thing as one "binary format" for floating point numbers. That's more than enough reason to believe why your function fails to work. Unless you can show us that 12.54 saved by your C++ runtime is binary equivalent to 12.54 saved by your Fortran program, then you're wasting your time.

    Why not just write a small C++ program and save 12.54 to a file. Now save 12.54 to a file in your Fortran program. Are both files exactly the same in terms of the bytes they store?

    In that event, strings are the most consistent way to store floating point numbers.

    Regards,

    Paul McKenzie
    Last edited by Paul McKenzie; April 2nd, 2013 at 07:44 PM.

  5. #5
    Join Date
    Apr 2013
    Posts
    6

    Re: Writing and Reading Binary data in FORTRAN and C++

    Why not just write a small C++ program and save 12.54 to a file. Now save 12.54 to a file in your Fortran program. Are both files exactly the same in terms of the bytes they store?
    Thanks for the useful information. I think I did a similar case before:
    If I write 12.54 to a binary file ( not console) with FORTRAN and then read that binary file with C++ it works fine. But in thatcase I am using ifstream to read the file and not using ReadFile() function. Where do you think the problem is?

  6. #6
    Join Date
    Apr 1999
    Posts
    27,427

    Re: Writing and Reading Binary data in FORTRAN and C++

    Quote Originally Posted by Vectorprg View Post
    To make the process faster I want to use binary format. It should write the binary representative of number 12.54
    Well, what is the binary representation of 12.54?

    That's the fly in the ointment. How is 12.54 represented in binary? It depends on the floating point format, and as I stated, the most popular is IEEE 754, but isn't the only format:

    http://en.wikipedia.org/wiki/Ieee_floating_point

    Having said this, even C++ programs can't guarantee that saving numbers in binary are readable by other C++ programs. You want to go a step further down this murky path and attempt to have C++ read a Fortran binary number. Either save the number as two integers (a whole and fractional part), or as a string. The former is how a protocol such as TWAIN represents floating point numbers, and that is to have two integers represent whole and fractional part of the number.

    Regards,

    Paul McKenzie

  7. #7
    Join Date
    Apr 1999
    Posts
    27,427

    Re: Writing and Reading Binary data in FORTRAN and C++

    Quote Originally Posted by Vectorprg View Post
    Thanks for the useful information. I think I did a similar case before:
    If I write 12.54 to a binary file ( not console) with FORTRAN and then read that binary file with C++ it works fine. But in thatcase I am using ifstream to read the file and not using ReadFile() function. Where do you think the problem is?
    First, I highly recommend you not try to read floating point numbers this way. You're risking having your data being unreadable if you change C++ compilers, or if you choose different options when building your C++ programs. Instead, the whole/frac is much more reliable, as you're dealing with integers.

    Second, what does your ifstream call look like?

    Regards,

    Paul McKenzie

  8. #8
    Join Date
    Aug 2000
    Location
    West Virginia
    Posts
    7,565

    Re: Writing and Reading Binary data in FORTRAN and C++

    You did not show the code where you convert the data read to a double.

    I imagine it would look like this:

    Code:
    // after the read file ...
    const int nDoubles = dwRead / sizeof(double);
    
    for (int i=0; i<nDoubles; ++i)
    {
       double x = *reinterpret_cast<double*>(&Buf[i*sizeof(double)]);
    }

  9. #9
    Join Date
    Apr 2013
    Posts
    6

    Re: Writing and Reading Binary data in FORTRAN and C++

    Quote Originally Posted by Philip Nicoletti View Post
    You did not show the code where you convert the data read to a double.

    I imagine it would look like this:

    Code:
    // after the read file ...
    const int nDoubles = dwRead / sizeof(double);
    
    for (int i=0; i<nDoubles; ++i)
    {
       double x = *reinterpret_cast<double*>(&Buf[i*sizeof(double)]);
    }
    I used exactly same code as you mentioned. But it does not give me the number. dwRead becomes equal to 6 which is less than size of a double number and does not make sense (sizeof(double) = 8)
    I still do not know where is my problem!

  10. #10
    VictorN's Avatar
    VictorN is online now Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Wallisellen (ZH), Switzerland
    Posts
    17,392

    Re: Writing and Reading Binary data in FORTRAN and C++

    Quote Originally Posted by Vectorprg View Post
    I used exactly same code as you mentioned. But it does not give me the number. dwRead becomes equal to 6 which is less than size of a double number and does not make sense (sizeof(double) = 8)
    I still do not know where is my problem!
    Well, did you do a very simple test Paul mentioned in the post#4:
    Quote Originally Posted by Paul McKenzie View Post
    Why not just write a small C++ program and save 12.54 to a file. Now save 12.54 to a file in your Fortran program. Are both files exactly the same in terms of the bytes they store?
    Last edited by VictorN; April 3rd, 2013 at 01:02 PM.
    Victor Nijegorodov

  11. #11
    Join Date
    Apr 2013
    Posts
    6

    Re: Writing and Reading Binary data in FORTRAN and C++

    did you do a verz simple test Paul mentioned in the post#4:
    Yes, If I write 12.54 to a binary file ( not console) with FORTRAN and then read that binary file with C++ it works fine. But in thatcase I am using ifstream to read the file and not using ReadFile() function.

  12. #12
    VictorN's Avatar
    VictorN is online now Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Wallisellen (ZH), Switzerland
    Posts
    17,392

    Re: Writing and Reading Binary data in FORTRAN and C++

    Quote Originally Posted by Vectorprg View Post
    Yes, If I write 12.54 to a binary file ( not console) with FORTRAN and then read that binary file with C++ it works fine. But in thatcase I am using ifstream to read the file and not using ReadFile() function.
    Then the problem seems to be with your ReadFile?
    Show your complete code for both case: when using ifstream and when using ReadFile
    Victor Nijegorodov

  13. #13
    Join Date
    Apr 2013
    Posts
    6

    Re: Writing and Reading Binary data in FORTRAN and C++

    Show your complete code for both case: when using ifstream and when using ReadFile
    Case1: using ReadFile()
    Code:
    #define BUF_SIZE 5000 
    BOOL bSuccess = FALSE;
    char Buf[BUF_SIZE];
    DWORD dwRead;
    for (;;) 
    { 
      bSuccess = ReadFile( V_hChildStd_OUT_Rd, Buf, BUF_SIZE, &dwRead, NULL);
      if( ! bSuccess || dwRead == 0 )   break; 
    }
    
    const int nDoubles = dwRead / sizeof(double);
    
    for (int i=0; i<nDoubles ; ++i)
    {
        double x = *reinterpret_cast<double*>(&chBuf[i*sizeof(double)]);
    }
    Case2: using fopen_s


    Code:
    double x;
    FILE* pFile;
    fopen_s(&pFile, PathName.Left(PathName.ReverseFind('\\')) + "\\Fortran.bin", "rb");
    fread((char*)&x,1,sizeof(double),pFile);
    fclose(pFile);

  14. #14
    VictorN's Avatar
    VictorN is online now Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Wallisellen (ZH), Switzerland
    Posts
    17,392

    Re: Writing and Reading Binary data in FORTRAN and C++

    I asked you to post the complete code!
    What is V_hChildStd_OUT_Rd? How do you obtain it?
    What does ReadFile return?
    What is the value of dwRead?
    Victor Nijegorodov

  15. #15
    Join Date
    Apr 1999
    Posts
    27,427

    Re: Writing and Reading Binary data in FORTRAN and C++

    Quote Originally Posted by Vectorprg View Post
    Case1: using ReadFile()
    Code:
    #define BUF_SIZE 5000 
    BOOL bSuccess = FALSE;
    char Buf[BUF_SIZE];
    DWORD dwRead;
    for (;;) 
    { 
      bSuccess = ReadFile( V_hChildStd_OUT_Rd, Buf, BUF_SIZE, &dwRead, NULL);
      if( ! bSuccess || dwRead == 0 )   break; 
    }
    
    const int nDoubles = dwRead / sizeof(double);
    
    for (int i=0; i<nDoubles ; ++i)
    {
        double x = *reinterpret_cast<double*>(&chBuf[i*sizeof(double)]);
    }
    Case2: using fopen_s


    Code:
    double x;
    FILE* pFile;
    fopen_s(&pFile, PathName.Left(PathName.ReverseFind('\\')) + "\\Fortran.bin", "rb");
    fread((char*)&x,1,sizeof(double),pFile);
    fclose(pFile);
    First, you do see that your ReadFile does much more than read. You are reading 5,000 bytes of potential data, and afterwords manipulating the returned buffer, all with the hopes that the number is a valid double.

    The fopen_s (which is not ifstream) does things simply. You are reading sizeof(double) bytes, and that's it. So why are you not doing the same thing with ReadFile()? You know you must read sizeof(double) bytes, you know that the buffer is really a pointer to a double, so why are you doing things so radically different with ReadFile() than for fopen_s?

    Third, if you're confident that your ReadFile approach is supposed to work, why are you not debugging it step by step to see where it breaks down?

    Last, the way you would want to write your code to ensure you're at least in sync with your Fortran program is this:

    For runtime check:
    Code:
    #include <assert.h>
    //...
    assert(sizeof(double) == 8);
    Alternate compile time check: (uses "old" C++ syntax)
    Code:
    char x__[sizeof(double) == 8];
    For the first example, a debug version of your program will abort once it is discovered that sizeof(double) is not 8. For the second example, your program will fail to compile if sizeof(double) is not 8. For the second example, you could also use the newer static_assert().

    Otherwise, your program will potentially run assuming that a double in C++ is the same as a double in Fortran (at least in terms of size) when it isn't.

    Regards,

    Paul McKenzie
    Last edited by Paul McKenzie; April 3rd, 2013 at 02:43 PM.

Page 1 of 2 12 LastLast

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Windows Mobile Development Center


Click Here to Expand Forum to Full Width

This is a CodeGuru survey question.


Featured


HTML5 Development Center