Link to home
Start Free TrialLog in
Avatar of scooter1
scooter1

asked on

Reading binary info from file

i wanna read this "box.exe" file but cant figure out how i have something like so:


 FILE *stream;
   int i;
   int mask = 0x00FF;

   if( (stream = fopen( "Box.exe", "rb" )) == NULL )
      printf( "Couldn't open file\n" );
   else
   {
      /* Read a word from the stream: */
      i = _getw( stream );

      /* If there is an error... */
      if( ferror( stream ) )
      {
         printf( "_getw failed\n" );
         clearerr( stream );
      }
      else
         printf( "First data word in file: 0x%x\n", i);
      fclose( stream );
   }

this gives the value in hex but it is reversed it gives :
0x905A4D should be 0x4D5A90   ?
ASKER CERTIFIED SOLUTION
Avatar of sdussinger
sdussinger

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of scooter1
scooter1

ASKER

that yields same results
that yields same results
How are you reading the first four bytes to know what the order should be?

--Steve
hex editor
It's been a while since I messed with this stuff...

The bytes are being read in correctly. I modified the code I posted earlier to display the bytes individually, and they come out in the order one would expect.

I created a dummy file with the letters ABCD in it, and read it using the code from earlier. When printing out the bytes individually I get 0x41 0x42 0x43 0x44. This is what I expected to see. When I print out the int using the %x I get 0x44434241. Backwards.

The problem must be then when the %x accesses the 4 bytes. It's performing the endian modifications and swapping the bytes.

Unfortunately, using a hex editor to look at the file doesn't always get you what you want. Because of the endian stuff, the order which the bytes are stored on disk may be different from the way they are interpreted as ints, etc.

The real question is what do you need to do with this information your read from the file? In order to compare the info read in from the file, you'll need to compare the bytes 1-by-1 or use some sort of endian-mapping macros to figure out the order of bytes. There is a whole set of macros in the GCC compiler to handle endian-ness, maybe they could help you.

Unfortunately, I'm a little rustier than I thought with this stuff. :-(

--Steve
how did you print out the bytes individually?
scooter,
In order to avoid the endian problems (as sdussinger pointed out this is), you need to avoid the built in data types.  These types will automatically be swapped in memory to the native endian order.  The way to avoid this is to allocate your own memory, and handle the information byte by byte. This way you are guaranteed to get the information in Big Endian, no matter which platform you are on.  Here is a modified example of your code..


   FILE *stream;
   int i;
   unsigned char * bytes;
   int mask = 0x00FF;

   if( (stream = fopen( "Box.exe", "rb" )) == NULL )
      printf( "Couldn't open file\n" );
   else
   {
      /* Read a word from the stream: */
      //i = _getw( stream );
     
      /* Create my own "integer" instead */
      bytes = malloc(sizeof(int));
      fread(bytes, sizeof(int), 1, stream);


      /* If there is an error... */
      if( ferror( stream ) )
      {
         printf( "_getw failed\n" );
         clearerr( stream );
      }
      else
      {
         printf( "First data word in file: ");
         /* Print the info byte by byte */
         printhex(bytes,sizeof(int));
         printf("\n");
      }
      fclose( stream );
      free(bytes);
   }
}

void
printhex(unsigned char * bytes, int length)
{
   int count;

   for (count = 0;count<length;count++)
   {
      printf("0x%x ",bytes[count]);
   }
}
Just as a side note, you will now get the data in exactly the order it is stored, but if you need to do any data manipulation or calculations, you will need to be very careful of your byte ordering.

Good Luck,
BD
Avatar of jkr
You have to re-arrange the byte order using the appropriate function:


#include <winsock.h>

//...

int bytes = fread ((void *) &i, 1, sizeof (int), stream);

//...

/*
The Windows Sockets ntohl function converts a u_long from TCP/IP network order to host byte order (which is big-endian).
*/

i = ntohl ( i);
So what i ended up doing is:

 FILE *stream;
 
   if( (stream = fopen( line, "rb" )) != NULL )
   {
       /* read in 1 character*/
       numread = fread( list, sizeof(unsigned char ), 1, stream );

        for(double x = 0; x < numbytes; x++)
        {
         fprint(stream2,"%.2x%c",list[0],' ');

          /* read in 1 character*/
         numread += fread( list, sizeof(unsigned char ), 1, stream );
    }