Thread: binary file i/o -- why doesn't this work?

  1. #1
    Registered User
    Join Date
    Feb 2003
    Posts
    596

    binary file i/o -- why doesn't this work?

    What's wrong with this code? Each time I run it, it gives a different (wrong) output. Makes no difference whether I use put() or <<.

    Code:
    #include <iostream>
    #include <fstream>
    using namespace std;
    
    int main () {
      int intval1 = 1919006563; // this is what I should get back
      int intval2, intval3;
      
      ofstream fout( "eof.dat", ios::binary );
      if( fout == NULL ) {
        cout << "couldn't open for output\n";
        return 1;
      }
    
    //  fout.put( 99 );  //01100011
    //  fout.put( 183 ); //10110111
    //  fout.put( 97 );  //01100001
    //  fout.put( 114 ); //01110010
      fout << (unsigned char)99;
      fout << (unsigned char)183;
      fout << (unsigned char)97;
      fout << (unsigned char)114;
      fout << intval1;
      fout.close();
      
      ifstream fin( "eof.dat", ios::binary );
      if( fin == NULL ) {
        cout << "couldn't open for input\n";
        return 1;
      }
    
      fin >> intval2 >> intval3;
      cout << "intval2 = " << intval2 << ", intval3 = " << intval3 << endl;
      fin.close();
      return 0;
    }
    On the other hand, using C i/o functions it behaves nicely:
    Code:
    #include <cstdio>
    
    int main () {
      int intval1, intval2, intval3;
      unsigned char charr[4];
      intval1 = 1919006563; // this is what I should get back
      void* vp;
      vp = &intval1;
      
      FILE* iofile;
      iofile = fopen( "test.dat", "wb" );
      if( iofile == NULL ) {
        printf("couldn't open for output\n");
        return 1;
      }
    
      fputc( 99, iofile );
      fputc( 183, iofile );
      fputc( 97, iofile );
      fputc( 114, iofile );
      fwrite( vp, 4, 1, iofile );
      fclose( iofile );
      
      iofile = fopen( "test.dat", "rb" );
      if( iofile == NULL ) {
        printf("couldn't open for input\n");
        return 1;
      }
      
      vp = &intval2;
      fread( vp, 4, 1, iofile );
      printf( "intval2 = %d\n", intval2);
      
      vp = charr;
      fread( vp, 1, 4, iofile );
      printf("chars = %d, %d, %d, %d\n", charr[0], charr[1], charr[2], charr[3]);
      fclose( iofile );
      return 0;
    }
    Is there any way to do this using C++ iostreams?

    Edit: It is not a mistake that I am swapping the uchars and the ints. I was intentionally trying to write 4 uchars and read back an int, and vice versa.
    Last edited by R.Stiltskin; 01-28-2009 at 05:17 PM. Reason: clarification

  2. #2
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    If you want the bits to go all the way through, then you should use an unformatted IO method: write(). Then you can read() it in.

    gg

  3. #3
    Registered User
    Join Date
    Feb 2003
    Posts
    596
    Thanks Codeplug. I see that write() and read(), using a void*, give the results I was looking for. Now I can get to the question that actually got me started with this foolishness, which is whether the same code will work on a Mac G5 or earlier. I understand that the PowerPC cpu is big-endian, but Wikipedia makes some ambiguous statements about the endianness being reversed by the motherboards of PowerPC systems. So can someone please tell me if this code gives the same results on a G4 or G5 Mac? The output should be:
    1919006563
    99
    183
    97
    114

    Code:
    #include <iostream>
    #include <fstream>
    using namespace std;
    
    int main () {
      int intval1 = 1919006563; // this is what I should get back when the chars are put together
      int intval2, intval3;
      unsigned char buffer[4];
      void* vp;
      ofstream fout( "eof.dat", ios::binary );
      if( fout == NULL ) {
        cout << "couldn't open for output\n";
        return 1;
      }
    
      buffer[0] = (unsigned char)99;
      buffer[1] = (unsigned char)183;
      buffer[2] = (unsigned char)97;
      buffer[3] = (unsigned char)114;
      vp = buffer;
      fout.write( (const char*)vp, 4 );
      vp = &intval1;
      fout.write( (const char*)vp, 4 );
      fout.close();
    
      ifstream fin( "eof.dat", ios::binary );
      if( fin == NULL ) {
        cout << "couldn't open for input\n";
        return 1;
      }
    
      vp = &intval2;
      fin.read( (char*)vp, 4 );
      cout << intval2 << endl;
      vp = buffer;
      fin.read( (char*)vp, 4 );
      for( int i = 0; i < 4; ++i ) {
        cout << (int)buffer[i] << endl;
      }
    
      fin.close();
      return 0;
    }

  4. #4
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    Well, you can always test for endianess with something like:
    Code:
        const short s = 1;
        bool LE =  *((const char*)&s) == 1;
    If the first byte where s begins in memory is least significant byte (or little end), then you're running on LE architecture.

    When you write 'buffer', you are in full control of the byte order in the file. When you write 'intval' the byte order is determined by the architecture.

    gg

  5. #5
    Registered User
    Join Date
    Feb 2003
    Posts
    596
    Yes, that would be easier. But my first concern was to experiment with different ways of moving data into & out of files.

    Thanks again.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. A development process
    By Noir in forum C Programming
    Replies: 37
    Last Post: 07-10-2011, 10:39 PM
  2. Formatting the contents of a text file
    By dagorsul in forum C++ Programming
    Replies: 2
    Last Post: 04-29-2008, 12:36 PM
  3. Can we have vector of vector?
    By ketu1 in forum C++ Programming
    Replies: 24
    Last Post: 01-03-2008, 05:02 AM
  4. File I/O problems!!! Help!!!
    By Unregistered in forum C Programming
    Replies: 4
    Last Post: 05-17-2002, 08:09 PM
  5. what does this mean to you?
    By pkananen in forum C++ Programming
    Replies: 8
    Last Post: 02-04-2002, 03:58 PM