-1

How come this program does not read a hex file correctly?

#include <stdio.h>
#include <stdlib.h>

char *buffer;
unsigned int fileLen;
void ReadFile(char *name);


void ReadFile(char *name)
{
        FILE *file;

        file = fopen(name, "rb");
        if (!file)
        {
                fprintf(stderr, "Unable to open file %s", name);
                return;
        }

        //Getting file length
        fseek(file, 0, SEEK_END);
        fileLen=ftell(file);
        fseek(file, 0, SEEK_SET);

        //Allocating memory
        buffer=(char *)malloc(fileLen+1);
        if (!buffer)
        {
                fprintf(stderr, "Mem error!");
                                fclose(file);
                return;
        }

        fread(buffer, fileLen, 1, file);
        fclose(file);


}

int main()
{
   var32 code;
   char filename[20];
   printf("Enter the file name: ");
   scanf("%s", &filename);
   ReadFile(filename);
   printf("FIle contents: %x\n",buffer);

}

If i print a huge hex file, it just prints 5 to 6 digits.

RajSanpui
  • 11,556
  • 32
  • 79
  • 146

3 Answers3

6
printf("FIle contents: %x\n",buffer);

"%x" just prints ONE hex value. It is printing the memory address of your buffer, not its contents.

Try changing:

    fread(buffer, fileLen, 1, file);
    fclose(file);

adding afterwards:

    ...
    fclose(file);
    size_t i;
    for (i = 0; i < fileLen; i++)
        printf("%02x ", buffer[i];

This will print the whole binary content. But it's not necessary to read the whole file to do this, you can output blocks of, say, 1 K at a time...

A different implementation

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#define BUFFER_SIZE     4096
int main(void)
{
     uint8_t  *buffer;  // Explicit 8 bit unsigned, but should equal "unsigned char"
     FILE     *file;
     char     filename[512];
     // We could also have used buffer[BUFFER_SIZE], but this shows memory alloc
     if (NULL == (buffer = malloc(BUFFER_SIZE)))
     {
          fprintf(stderr, "out of memory\n");
          return -1;
     }
     printf("Enter the file name: ");
     // Read a line terminated by LF. Max filename size is MAXPATH, or 512
     fgets(filename, 512, stdin);
     // Trim filename (Windows: CHECK we don't get \r instead of \n!)
     {
         // Being inside a { }, crlf won't be visible outside, which is good.
         char     *crlf;
         if (NULL != (crlf = strchr(filename, '\n')))
              *crlf = 0x0;
     }
     if (NULL == (file = fopen(filename, "rb")))
     {
         fprintf(stderr, "File not found: '%s'\n", filename);
         return -1;
     }
     while(!feof(file) && !ferror(file))
     {
          size_t i, n;
          if (0 == (n = (size_t)fread(buffer, sizeof(uint8_t), BUFFER_SIZE, file)))
               if (ferror(file))
                    fprintf(stderr, "Error reading from %s\n", filename);
                    // Here, n = 0, so we don't need to break: next i-cycle won't run
          for (i = 0; i < n; i++)
          {
               printf("%02x ", buffer[i]);
               if (15 == (i % 16))
                    printf("\n"); // Every 16th byte, a newline
          }
     }
     fclose(file); // file = NULL; // This ensures file won't be useable after fclose
     free(buffer); // buffer = NULL; // This ensures buffer won't be useable after free
     printf("\n");
     return 0;
}
LSerni
  • 55,617
  • 10
  • 65
  • 107
  • Didn't understand. What do i need to change `fread(buffer, fileLen, 1, file);` these 2 statements with? – RajSanpui Jul 09 '12 at 13:00
  • You need to add those three lines (size_t i, etc.) after fclose(file), in order to output the file's contents. – LSerni Jul 09 '12 at 13:01
  • `printf("%02x ", buffer[i])` it prints digits correctly, but the hex as suppose "b2" as "fffffb2" also double zeros as separated ones. – RajSanpui Jul 09 '12 at 13:17
  • Ah, sorry. Declare buffer as "unsigned char", not char. Just for the lulz, I'll also add a different code sample. – LSerni Jul 09 '12 at 13:42
4

The printf() statement will print the address of buffer, in hexadecimal format. You need to printf() each byte in buffer (and you must null terminate buffer so the caller knows when to stop or return the number of bytes in buffer to the caller) and ensure caller knows how many bytes are in buffer (null termination is not safe as reading in binary).

Also:

  • ensure buffer is not null before dereferencing (which is required to print byte-by-byte)
  • check the return value of fread() to ensure it was successful
  • remember to free() buffer when no longer required
  • cast of return value of malloc() unrequired (see Do I cast the result of malloc?)
  • restrict the number of bytes read by scanf() to avoid buffer overrun: scanf("%19s", filename);
  • code is an unused local variable
Community
  • 1
  • 1
hmjd
  • 120,187
  • 20
  • 207
  • 252
-1

If with hex you mean binary, you can't print those directly, the output will end at the first zero byte in the file.

Also, if the file cannot be found, you say "Unable to open file" first and then continue with saying "File contents: ..."

And as the others point out, you are printing the buffer the wrong way.

And you don't free the buffer.

Mr Lister
  • 45,515
  • 15
  • 108
  • 150