CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 15 of 16

Hybrid View

  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,449

    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,449

    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,449

    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

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

    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

  8. #8
    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.

  9. #9
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,395

    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

  10. #10
    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);

  11. #11
    Join Date
    Apr 1999
    Posts
    27,449

    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.

  12. #12
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,395

    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

  13. #13
    2kaud's Avatar
    2kaud is online now Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

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

    As the problem is with ReadFile, then the format of data stored in the file must be correct as fread works. The following test program (with no error checking as just a quick test) writes a double to a file using fwrite then reads it from the file using both fread and ReadFile and in both cases produces the correct output.

    Code:
    #include <stdio.h>
    #include <windows.h>
    
    int main ()
    {
    double val = 12.54;
    
    double	x,
    	rfx;
    
    FILE*	pFile;
    
    DWORD	dwRead;
    
    HANDLE	fh;
    
    	pFile = fopen("double", "wb");
    	fwrite(&val, sizeof(double), 1, pFile);
    	fclose(pFile);
    
    	x = 0;
    	pFile = fopen("double", "rb");
    	fread((char*)&x, sizeof(double), 1, pFile);
    	printf("read : %f\n", x);
    	fclose(pFile);
    
    	rfx = 0;
    	fh = CreateFile("double", FILE_READ_DATA, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    	ReadFile(fh, (char*)&rfx, sizeof(double), &dwRead, NULL);
    	printf("ReadFile : %f\n", rfx);
    
    	return (0);
    }
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

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
  •  





Click Here to Expand Forum to Full Width

Featured