Gio
Gio

Reputation: 3340

How to read a char array stored in a file, into a char buffer during runtime

I'm working in C and I'm modifying existing code.

I have a char array which is stored in a file as follows:

"\x01\x02\x03"
"\x04\x05\x06"
"\x07\x08\x09"

In the original source code this char array is included as follows:

const static char chs[] =
#include "file.h"
;

I'm modifying this code to load the file into a char array during runtime (to get the exact same result as with the above approach) instead of it to be included by the pre-processor. My first approach was to simply read the file into a char buffer, as follows:

FILE *fp;
const char *filename = "file.h";
fp = fopen (filename, "rb");
assert(fp != NULL);

fseek(fp, 0L, SEEK_END);
long int size = ftell(fp);
rewind(fp);

// read entire file into the buffer
char *buffer = (char*)malloc(sizeof(char) * size);
size_t nrOfBytesRead = fread(buffer, 1, size, fp);

However I've quickly discovered that this is not correct. The file already contains the exact code representation of the char array, I cannot simply read it into a char buffer and get the same result as the include approach.

What is the best way to get my char array which is stored in file, into a char array during runtime?

Upvotes: 2

Views: 2245

Answers (2)

user3121023
user3121023

Reputation: 8286

This should read the hex values from the file and save them to buffer.
fgets() reads each line from the file.
sscanf() reads each hex value from the line.
The format string for sscanf, "\\x%x%n", scans the backslash, an x, the hex value and stores the number of characters processed by the scan. The number of characters processed is used to advance through the line. This is needed if some lines have a different number of hex values.

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

int main()
{
    char line[100] = {'\0'};
    unsigned char *buffer = NULL;
    unsigned char *temp = NULL;
    unsigned int hex = 0;
    int size = 0;
    int offset = 0;
    int used = 0;
    int bufferused = 0;
    int increment = 100;
    int each = 0;
    FILE *pf = NULL;

    if ( ( pf = fopen ( "file.h", "r")) != NULL) {
        while ( fgets ( line, sizeof ( line), pf)) {//get each line of the file
            offset = 1;//to skip leading quote
            //sscanf each hex value in the line
            while ( ( sscanf ( line + offset, "\\x%x%n", &hex, &used)) == 1) {
                offset += used;// to advance through the line
                if ( bufferused >= size) {
                    temp = realloc ( buffer, size + increment);
                    if ( temp == NULL) {
                        //one way to handle the failure
                        printf ( "realloc failed\n");
                        free ( buffer);
                        exit (1);
                    }
                    buffer = temp;
                    size += increment;
                }
                buffer[bufferused] = hex;
                bufferused++;
            }
        }
        fclose ( pf);
    }
    for ( each = 0; each < bufferused; each++) {
        printf ( "%x\n", buffer[each]);
    }
    free ( buffer);

    return 0;
}

Upvotes: 1

Steve Summit
Steve Summit

Reputation: 47923

As you've seen, when you read the file using fread it reads it byte for byte. It doesn't get any of the syntactic processing that the compiler does on your source files. It doesn't know that strings live inside of quotes. It doesn't map escape sequences like \x01 into single bytes.

You have several different possibilities for fixing this:

  1. Teach your program how to do that processing as it reads the file. This would be a fair amount of work.
  2. Put just the bytes you want into the file.
  3. Pick a different encoding for your file.

To say a little more about #2: If you don't want to change your file-reading code, what you can do is to create an (in this case) 9-byte file containing just the nine bytes you want. Since your nine bytes are not text, it'll end up being a "binary" file, which you won't be able to straightforwardly edit with an ordinary text editor, etc. (In fact, depending on the tools you have available to you, it might be challenging just to create this particular 9-byte file.)

So if you can't use #1 or #2, you might want to go with #3: pick a brand-new way to encode the data in the file, easier to parse than #1, but easier to prepare than #2. My first thought would be to have the file be hexadecimal. That is, the file would contain

010203040506070809

or

010203
040506
070809

Your file-reading code, instead of the single call to fread, would read two characters at a time and assemble them into bytes for your array. (I'd sketch this out for you, but the compilation I was waiting for has finished, and I ought to get back to my job.)

Upvotes: 5

Related Questions