13

Possible Duplicate:
Easiest way to get file's contents in C

My program reads files that span over many lines. I would like to hold the content of a file in a single string.

I don't know the number of lines of my file before execution, however I have fixed a line size to MAX_LINE_LEN.

How can you do that?

Community
  • 1
  • 1
rahmu
  • 5,708
  • 9
  • 39
  • 57

2 Answers2

27

The function fread() doesn't care about line breaks. The following code reads the contents of input_file_name and saves them to the array file_contents:

char *file_contents;
long input_file_size;
FILE *input_file = fopen(input_file_name, "rb");
fseek(input_file, 0, SEEK_END);
input_file_size = ftell(input_file);
rewind(input_file);
file_contents = malloc(input_file_size * (sizeof(char)));
fread(file_contents, sizeof(char), input_file_size, input_file);
fclose(input_file);

You can only make a string of this array if input_file_name contains the \0 character. If it does not, change the last three lines to:

file_contents = malloc((input_file_size + 1) * (sizeof(char)));
fread(file_contents, sizeof(char), input_file_size, input_file);
fclose(input_file);
file_contents[input_file_size] = 0;
Matt
  • 11,157
  • 26
  • 81
  • 110
Dennis
  • 14,264
  • 2
  • 48
  • 57
  • 1
    +1 but change `long long` to `size_t`, or at least use `long`, the actual return type of `ftell`. – Chris Lutz Oct 22 '11 at 01:17
  • Done. Thanks for the observation. @rahmu: That means that, if `sizeof(long) == 4`, the above will only work for files smaller than 4 GiB. – Dennis Oct 22 '11 at 01:19
  • Also, shouldn't the last line be `file_contents[input_file_size + 1] = '\0';` ? – Chris Jan 19 '14 at 19:23
  • 1
    @Chris: No. An array `a` of size two has the elements `a[0]` and `a[1]`. Likewise, the last element of an array `file_contents` of size `input_file_size + 1` is `file_contents[input_file_size]`. As for `0` vs `\0`, using a character constant or its integer representation makes no difference. – Dennis Jan 19 '14 at 21:11
  • Using this on certain linux system files, input_file_size is returned as 1 block, regardless of content. A solution is to terminate the string using the number of bytes read by fread: `bytes_read = fread(...); file_contents[bytes_read] = 0;` – John Jul 15 '14 at 12:27
  • There seem to be security issues related to using fseek/ftell for determining the file size: https://www.securecoding.cert.org/confluence/display/c/FIO19-C.+Do+not+use+fseek%28%29+and+ftell%28%29+to+compute+the+size+of+a+regular+file – Niklas Peter Jun 01 '16 at 10:39
3

1) figure out the size of the file with fstat.

2) alloc a zeroed buffer of this length + 1

3) use fread to read the file contents into the buffer

James
  • 9,064
  • 3
  • 31
  • 49
  • 4) Add a null terminator at the end. (EDIT: Okay, I see you said "zeroed buffer", but why spend all the time zeroing every byte if you overwrite it anyway? Not that it matters in real life, but still.) – EboMike Oct 22 '11 at 01:11
  • fair point. although i'd argue that the time taken to zero a buffer is negligible compared to the I/O overhead unless the file is huge. The user could just zero the last byte. – James Oct 22 '11 at 01:18
  • 1
    If you use `calloc`, on most OSes it'll be the same speed as `malloc` because the OS does something in the background to make sure memory is zeroed-out (to make sure `calloc(8 * getpagesize())` doesn't take forever), but it is, of course, no guarantee. – Chris Lutz Oct 22 '11 at 01:23
  • @James: Absolutely, that's why I said it doesn't matter in real life. I'm just so used to working in an environment where you count every cycle that I couldn't help but nitpick :) – EboMike Oct 22 '11 at 01:37
  • What is the size of the file changes between `fstat` and `fopen`? – joeytwiddle Jun 11 '15 at 20:35