How to read the contents of a file into a string in C?

What is the easiest way (least error prone, smallest lines of code, however you want to interpret it) to open a C file and read its contents in a line (char *, char [], whatever)?

+80
c string file
Oct 06 '08 at 14:32
source share
11 answers

I try to just load the entire buffer as a raw piece of memory into memory and do the parsing myself. This way, I have the best control over what standard lib does on multiple platforms.

This is the stub I use for this. you can also check error codes for fseek, ftell and fread. (omitted for clarity).

char * buffer = 0; long length; FILE * f = fopen (filename, "rb"); if (f) { fseek (f, 0, SEEK_END); length = ftell (f); 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... } 
+121
Oct. 06 '08 at 14:37
source share
— -

Another, unfortunately, highly OS-dependent solution is to display the file in memory. Benefits typically include read performance and reduced memory usage, since application views and the operating system file cache can actually share physical memory.

POSIX code will look like this:

 int fd = open("filename", O_RDONLY); int len = lseek(fd, 0, SEEK_END); void *data = mmap(0, len, PROT_READ, MAP_PRIVATE, fd, 0); 

On the other hand, Windows is a bit more complicated, and, unfortunately, there is no compiler under test in front of me, but the functionality is provided by CreateFileMapping() and MapViewOfFile() .

+24
Oct 06 '08 at 15:37
source share

If "read its contents to a string" means that the file does not contain characters with code 0, you can also use the getdelim () function, which either takes a block of memory and redistributes it if necessary, or simply allocates the entire buffer for you and read the file into him until you meet the specified delimiter or end of file. Just pass '\ 0' as a delimiter to read the entire file.

This feature is available in the GNU C library, http://www.gnu.org/software/libc/manual/html_mono/libc.html#index-getdelim-994

Sample code may look as simple as

 char* buffer = NULL; size_t len; ssize_t bytes_read = getdelim( &buffer, &len, '\0', fp); if ( bytes_read != -1) { /* Success, now the entire file is in the buffer */ 
+10
06 Oct '08 at 15:24
source share

If the file is a text file and you want to get text line by line, the easiest way is to use fgets ().

 char buffer[100]; FILE *fp = fopen("filename", "r"); // do not use "rb" while (fgets(buffer, sizeof(buffer), fp)) { ... do something } fclose(fp); 
+6
Oct 08 '08 at 21:02
source share

If you read special files such as stdin or pipe, you cannot use fstat to get the file size in advance. Also, if you are reading a binary file, fgets is going to lose line size information due to the embedded "\ 0" characters. The best way to read a file is to use read and realloc:

 #include <stdio.h> #include <unistd.h> #include <errno.h> #include <string.h> int main () { char buf[4096]; ssize_t n; char *str = NULL; size_t len = 0; while (n = read(STDIN_FILENO, buf, sizeof buf)) { if (n < 0) { if (errno == EAGAIN) continue; perror("read"); break; } str = realloc(str, len + n + 1); memcpy(str + len, buf, n); len += n; str[len] = '\0'; } printf("%.*s\n", len, str); return 0; } 
+6
Nov 24 '13 at 19:40
source share

Note: this is a variation of the accepted answer above.

Here is a way to do this, complete with error checking.

I added a size check to exit when the file was larger than 1 GiB. I did this because the program puts the entire file in a line that can use too much RAM and crash the computer. However, if this does not bother you, you can simply remove it from the code.

 #include <stdio.h> #include <stdlib.h> #define FILE_OK 0 #define FILE_NOT_EXIST 1 #define FILE_TO_LARGE 2 #define FILE_READ_ERROR 3 char * c_read_file(const char * f_name, int * err, size_t * f_size) { char * buffer; size_t length; FILE * f = fopen(f_name, "rb"); size_t read_length; if (f) { fseek(f, 0, SEEK_END); length = ftell(f); fseek(f, 0, SEEK_SET); // 1 GiB; best not to load a hole large file in one string if (length > 1073741824) { *err = FILE_TO_LARGE; return NULL; } buffer = (char *)malloc(length + 1); if (length) { read_length = fread(buffer, 1, length, f); if (length != read_length) { *err = FILE_READ_ERROR; return NULL; } } fclose(f); *err = FILE_OK; buffer[length] = '\0'; *f_size = length; } else { *err = FILE_NOT_EXIST; return NULL; } return buffer; } 

And check for errors:

 int err; size_t f_size; char * f_data; f_data = c_read_file("test.txt", &err, &f_size); if (err) { // process error } 
+2
Jan 6 '19 at 0:48
source share

If you use glib , you can use g_file_get_contents ;

 gchar *contents; GError *err = NULL; g_file_get_contents ("foo.txt", &contents, NULL, &err); g_assert ((contents == NULL && err != NULL) || (contents != NULL && err == NULL)); if (err != NULL) { // Report error to user, and free error g_assert (contents == NULL); fprintf (stderr, "Unable to read file: %s\n", err->message); g_error_free (err); } else { // Use file contents g_assert (contents != NULL); } } 
+1
Oct 07 '16 at 10:24
source share

Just modified from the accepted answer above.

 #include <stdio.h> #include <stdlib.h> #include <assert.h> char *readFile(char *filename) { FILE *f = fopen(filename, "rt"); assert(f); fseek(f, 0, SEEK_END); long length = ftell(f); fseek(f, 0, SEEK_SET); char *buffer = (char *) malloc(length + 1); buffer[length] = '\0'; fread(buffer, 1, length, f); fclose(f); return buffer; } int main() { char *content = readFile("../hello.txt"); printf("%s", content); } 
+1
Nov 09 '17 at 7:10
source share
 // Assumes the file exists and will seg. fault otherwise. const GLchar *load_shader_source(char *filename) { FILE *file = fopen(filename, "r"); // open fseek(file, 0L, SEEK_END); // find the end size_t size = ftell(file); // get the size in bytes GLchar *shaderSource = calloc(1, size); // allocate enough bytes rewind(file); // go back to file beginning fread(shaderSource, size, sizeof(char), file); // read each char into ourblock fclose(file); // close the stream return shaderSource; } 

This is a pretty rude decision because nothing is checked for null.

0
May 15 '16 at 17:49
source share

I will add my version based on the answers here, just for reference. My code takes into account sizeof (char) and adds some comments to it.

 // Open the file in read mode. FILE *file = fopen(file_name, "r"); // Check if there was an error. if (file == NULL) { fprintf(stderr, "Error: Can't open file '%s'.", file_name); exit(EXIT_FAILURE); } // Get the file length fseek(file, 0, SEEK_END); long length = ftell(file); fseek(file, 0, SEEK_SET); // Create the string for the file contents. char *buffer = malloc(sizeof(char) * (length + 1)); buffer[length] = '\0'; // Set the contents of the string. fread(buffer, sizeof(char), length, file); // Close the file. fclose(file); // Do something with the data. // ... // Free the allocated string space. free(buffer); 
0
Jul 07 '19 at 16:59
source share

easy and neat (provided that the contents of the file are less than 10000):

 void read_whole_file(char fileName[1000], char buffer[10000]) { FILE * file = fopen(fileName, "r"); if(file == NULL) { puts("File not found"); exit(1); } char c; int idx=0; while (fscanf(file , "%c" ,&c) == 1) { buffer[idx] = c; idx++; } buffer[idx] = 0; } 
0
Aug 15 '19 at 14:40
source share



All Articles