Question

What is the best way to get the contents of a file into a single character array?

I have read this question:

Easiest way to get file's contents in C

But from the comments, I've seen that the solution isn't great for large files. I do have access to the stat function. If the file size is over 4 gb, should I just return an error?

The contents of the file is encrypted and since it's supplied by the user it could be as large as anyone would want it to be. I want it to return an error and not crash if the file is too big. The main purpose of populating the character array with the contents of a file, is to compare it to another character array and also (if needed and configured to do so) to log both of these to a log file (or multiple log files if necessary).

Was it helpful?

Solution

You may use fstat(3) from sys/stat.h. Here is a little function to get size of the file, allocate memory if file is less than 4GB's and return (-1) otherwise. It reads the file to the char array passed to char *buffer a char *, which contains the contents of the whole file.It should be free'd after use.

#include <stdio.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>

char *loadlfile(const char *path)
{
    int file_descr;
    FILE *fp;
    struct stat buf;
    char *p, *buffer;

    fstat((file_descr = open(path, O_RDONLY)), &buf);

// This check is done at preprocessing and requires no check at runtime.
// It basically means "If this machine is not of a popular 64bit architecture,
// it's probably not 128bit and possibly has limits in maximum memory size.
// This check is done for the sake of omission of malloc(3)'s unnecessary
// invocation at runtime.

//    Amd 64               Arm64                      Intel 64       Intel 64 for Microsofts compiler.
#if !defined(__IA_64) || !defined(__aarch64__) || !defined(__ia64__) || !defined(_M_IA64)
#define FILE_MAX_BYTES (4000000000)
    // buf.st_size is of off_t, you may need to cast it.
    if(buf.st_size >= FILE_MAX_BYTES-1)
        return (-1);
#endif

    if(NULL == (buffer = malloc(buf.st_size + 1)))
        return NULL;

    fp = fdopen(file_descr, "rb");

    p = buffer;
    while((*p++ = fgetc(fp)) != EOF)
        ;
    *p = '\0';

    fclose(fp);
    close(file_descr);
    return buffer;
}

A very broad list of pre-defined macros for various things can be found @ http://sourceforge.net/p/predef/wiki/Home/. The reason for the architecture and file size check is, malloc can be expensive at times and it is best to omit/skip it's usage when it is not needed. And querying a memory of max. 4gb for a whole block of 4gb storage is just waste of those precious cycles.

OTHER TIPS

From that guy's code just do, if I understand your question correctly:

    char * buffer = 0;
    long length;
    FILE * f = fopen (filename, "rb");

    if (f)
    {
    fseek (f, 0, SEEK_END);
    length = ftell (f);
    if(length > MY_MAX_SIZE) {
          return -1;
    }

     fseek (f, 0, SEEK_SET);
     buffer = malloc (length);
    if (buffer)
    {
    fread (buffer, 1, length, f);
    }
    fclose (f);
    }

    if (buffer)
    {
      // start to process your data / extract strings here...
    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top