You are here:

C++/Hexadecimal file to new file with binary values

Advertisement


Question
I have been trying to get help with this everywhere and no luck.  I'm probably making it harder than it is.  I have a file that is all hexadecimal values and am using fread to read the file into a buffer object that is the size of the file.  I have created a string array that holds the hexadecimal values and I need to look each value up in the file and write it to a new file in it's binary form.  I've been told that I need to combine two hexadecimal values at one time to form a byte and that the right shift operator will be needed.  That is confusing me a little.  As of now I can read the file into the buffer and write the same data to a new file with fwrite.  Here is my code so far.  If you could give me suggestions, I would greatly appreciate it. I know the code is not in the greatist format but hopefully readable. Thanks in advance.

#include <vcl\condefs.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fstream.h>
#include <conio.h>

//---------------------------------------------------------

#pragma argsused

int main()
{
       FILE * sigfile;
       FILE * newfile;
       long lSize = 0;
       size_t bytes;

       //--------------------------------------------------
       // open existing file and error check to screen
       sigfile = fopen  ("c:\\SIGNIMAGE.S050024041.01.SPACE.txt", "r");

       if (sigfile == NULL)
       {
         printf ("Error opening file...\n");
         return 1;
       }
       else { printf ("File opened successfully!\n"); }

       //--------------------------------------------------
       //obtain file size
       fseek (sigfile, 0, SEEK_END);
       lSize = ftell (sigfile);
       fseek (sigfile, 0L, SEEK_SET);

       // allocate memory to heap
       char * buffer = new char [lSize];

       //--------------------------------------------------
       // read file with error handling
       bytes = fread (buffer, 1, lSize, sigfile);
       printf ("%u\n", bytes);
       if (bytes == NULL)
       {
         printf ("Error reading file...\n");
         return 1;
       }
       else { printf ("File read.\n"); }

       //--------------------------------------------------
       // define lookup table
       char hexValue[] = "'0''1''2''3''4''5''6''7''8''9'ABCDEF";

       // combare buffer value to hexadecimal value
       unsigned char reg;
       char ch = fgetc(sigfile);
       printf ("%c", ch);
       for (char i=0; i<16; i++)
       {

         if(hexValue[i] == ch);
         {
         reg |= i << 4;
         }
       }


       //--------------------------------------------------
       // create new file and do error checking to screen
       newfile = fopen ("c:\\converted_file.txt", "w");

       if (newfile == NULL)
       {
         printf ("Error creating file...\n");
         return 1;
       }
       else { printf ("File created successfully!\n"); }

       //--------------------------------------------------
       // write data to new file and error check

       if (fwrite (buffer, 1, lSize, newfile) < lSize)
       {
         printf ("Error writing file...\n");
         return 1;
       }
       else { printf ("File written.\n"); }

       //--------------------------------------------------
       //close file
       fclose (sigfile);
       fclose (newfile);
       delete[] buffer;
       //--------------------------------------------------
       return 0;
}


Answer
A perfect question for someone like me who's written tools.
Tips:

1)  Use the filelength function instead of fseek/ftell for file size.

2)  NULL is a pointer.  Compare bytes from fread to 0, not NULL.

3)  If you read the entire file into buffer, why using fgetc in the loop?

So, the input file has for example:

"127EA980" and you want bytes 0x12, 0x7E, 0xA9, 0x80

Don't read into buffer.  Allocate buffer to 1/2 the size of the file (because hex is 2 ASCII bytes for 1 binary byte).  Something like this (which I did not test!):

for( int byteCount = 0; byteCount < bytes / 2; ++byteCount )
 {
 unsigned char fileByte, byte;
 static unsigned char lookup[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15 };
 
 fileByte = fgetc( sigfile );
 byte = lookup[ (fileByte & 0x3F) - '0' ] << 4;
 fileByte = fgetc( sigfile );
 byte += lookup[ (fileByte & 0x3F) - '0' ];
 buffer[ byteCount ] = byte;
 }

Then fwrite buffer for bytes / 2 length.

The & 0x3F is just a safety code to ensure the byte is uppercase or the lookup fails.  If you know without a doubt it's in upper case you can remove this.  For really robust but slower code:

if( fileByte >= '0' && fileByte <= '9' || fileByte >= 'A' && fileByte <= 'Z' || fileByte >= 'a' && fileByte <= 'z' )
 process the byte

Bill

C++

All Answers


Answers by Expert:


Ask Experts

Volunteer


Bill A

Expertise

I can answer questions about C++, programming algorithms, Windows programming in MFC (which is C++). I cannot answer questions about STL (templates) and I have no experience with Linux. I do enjoy reviewing code and critiquing it or finding problems in it. I will also gladly show better algorithms or methods if you want to take advantage of that.

Experience

I've developed a commercial embedded C compiler/assembler and IDE with debugger toolset, of which the IDE and debugger are written in C++. I work in the industry writing high tech embedded programs and Windows programs to communicate with the embedded devices.

Publications
Book: Embedded Systems Design using the Rabbit 3000 Microprocessor Authored Chapter 10 in its entirety.

Education/Credentials
BS Computer Engineering

©2016 About.com. All rights reserved.