2

I'm looking for a cross platform (Windows + Linux) solution to reading the contents of an entire file into a char *.

This is what I've got now:

FILE *stream;
char *contents;
fileSize = 0;

//Open the stream
stream = fopen(argv[1], "r");

//Steak to the end of the file to determine the file size
fseek(stream, 0L, SEEK_END);
fileSize = ftell(stream);
fseek(stream, 0L, SEEK_SET);

//Allocate enough memory (should I add 1 for the \0?)
contents = (char *)malloc(fileSize);

//Read the file 
fscanf(stream, "%s", contents);     

//Print it again for debugging
printf("Read %s\n", contents);

Unfortunately this will only print the first line in the file so I assume that fscanf stops at the first newline character. However I would like to read the entire file including, and preserving, the new line characters. I'd prefer not to use a while loop and realloc to manually construct the entire string, I mean there has to be a simpler way?

Roy T.
  • 9,429
  • 2
  • 48
  • 70

4 Answers4

8

Something like this, may be?

FILE *stream;
char *contents;
fileSize = 0;

//Open the stream. Note "b" to avoid DOS/UNIX new line conversion.
stream = fopen(argv[1], "rb");

//Seek to the end of the file to determine the file size
fseek(stream, 0L, SEEK_END);
fileSize = ftell(stream);
fseek(stream, 0L, SEEK_SET);

//Allocate enough memory (add 1 for the \0, since fread won't add it)
contents = malloc(fileSize+1);

//Read the file 
size_t size=fread(contents,1,fileSize,stream);
contents[size]=0; // Add terminating zero.

//Print it again for debugging
printf("Read %s\n", contents);

//Close the file
fclose(stream);
free(contents);
Paul Rooney
  • 20,879
  • 9
  • 40
  • 61
Senna
  • 368
  • 1
  • 5
  • Works perfectly, note that you don't need the size_t size since you already have fileSize. Accept for clearest explanation! – Roy T. Aug 03 '12 at 10:29
  • You do need size_t size, since you won't necessary read as many bytes as you asked (for whatever reason). And your allocated buffer won't necessary have anything beyond read chunk filled with zero... and we really don't want to print garbage: it ends badly on Windows, and can do nasty things to terminal on UNIX. – Senna Aug 03 '12 at 10:33
0

The function fread will read from the stream and not terminate on end-of-line characters.

From the man page, you have:

size_t fread(void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream);

which reads in nitems of size size.

borrible
  • 17,120
  • 7
  • 53
  • 75
0

fread reads all the files as-is:

 if (fread(contents, 1, fileSize, stream) != fileSize) {
    /* error occurred */
 }
Ilmo Euro
  • 4,925
  • 1
  • 27
  • 29
0

I've got this:

ssize_t filetomem(const char *filename, uint8_t **result)
{ 
    ssize_t size = 0;
    FILE *f = fopen(filename, "r");
    if (f == NULL) 
    { 
        *result = NULL;
        return -1;
    } 
    fseek(f, 0, SEEK_END);
    size = ftell(f);
    fseek(f, 0, SEEK_SET);
    *result = malloc(size);
    if (size != fread(*result, sizeof(**result), size, f)) 
    { 
        free(*result);
        return -2;
    } 

    fclose(f);
    return size;
}

Meaning of return value:

  • Positive or 0: successfully read the file
  • minus one: couldn't open file (possibly no such file)
  • minus two: fread() failed