How to copy a text file to a string in C?

I need to copy the contents of a text file into a dynamically allocated array of characters.

My problem is getting the size of the contents of the file; Google shows that I need to use fseek and ftell , but for this, the file, apparently, needs to be opened in binary mode, and this only gives garbage.

EDIT: I tried to open text mode, but I get weird numbers. Here's the code (I skipped a simple error check for clarity):

 long f_size; char* code; size_t code_s, result; FILE* fp = fopen(argv[0], "r"); fseek(fp, 0, SEEK_END); f_size = ftell(fp); /* This returns 29696, but file is 85 bytes */ fseek(fp, 0, SEEK_SET); code_s = sizeof(char) * f_size; code = malloc(code_s); result = fread(code, 1, f_size, fp); /* This returns 1045, it should be the same as f_size */ 
+4
source share
10 answers

The root of the problem is here:

 FILE* fp = fopen(argv[0], "r"); 

argv [0] is your executable program, not a parameter. This, of course, will not be a text file. Try argv [1] and see what happens next.

+14
source

You cannot determine the file size in characters without reading data, unless you use a fixed-width encoding.

For example, a file in UTF-8 with a length of 8 bytes can contain from 2 to 8 characters.

This is not a limitation of file APIs, it is a natural limitation of the lack of direct matching from “binary data size” to “character count”.

If you have a fixed-width encoding, you can simply divide the file size in bytes by the number of bytes per character. ASCII is the most obvious example of this, but if your file is encoded in UTF-16 and you end up in a system that treats UTF-16 code points as a "native" internal character type (which includes Java, .NET, and Windows), then you you can predict the number of "characters" to highlight, as if UTF-16 was a fixed width. (UTF-16 is variable width due to Unicode characters above U + FFFF, which are encoded at multiple code points, but many time developers ignore this.)

+5
source

If you are developing Linux (or other Unix-like operating systems), you can get the size of the file with the status before opening the file:

 #include <stdio.h> #include <sys/stat.h> int main() { struct stat file_stat; if(stat("main.c", &file_stat) != 0) { perror("could not stat"); return (1); } printf("%d\n", (int) file_stat.st_size); return (0); } 

EDIT: As I see the code, I need to get in line with other posters:

An array that takes arguments from a program call is constructed like this:

[0] the name of the program itself
[1] first argument given
[2] second argument given
[n] n-th argument specified

You should also check argc before trying to use a field other than the '0' argv array:

 if (argc < 2) { printf ("Usage: %s arg1", argv[0]); return (1); } 
+2
source

I am sure argv [0] will not be a text file.

+2
source

Give it a try (did not compile it, but I did it bazillion times, so I'm sure it is at least close):

 char* readFile(char* filename) { FILE* file = fopen(filename,"r"); if(file == NULL) { return NULL; } fseek(file, 0, SEEK_END); long int size = ftell(file); rewind(file); char* content = calloc(size + 1, 1); fread(content,1,size,file); return content; } 
+2
source

You can use fseek for text files.

  • fseek to the end of the file
  • ftell offset
  • fseek back to top

and you have file size

+1
source

argv [0] is the path to the executable, and therefore argv [1] will be the first user to log in. Try changing and adding some simple error checks, for example, checking if fp == 0, and we can help you.

+1
source

You can open the file, place the cursor at the end of the file, save the offset and return to the beginning of the file and make changes.

0
source

The type is hard without sample code, but fstat (or stat) will tell you how big the file is. You select the required memory and insert the file.

0
source

Another approach is to read the file at a time and expand the dynamic buffer as needed:

 #include <stdio.h> #include <stdlib.h> #include <string.h> #define PAGESIZE 128 int main(int argc, char **argv) { char *buf = NULL, *tmp = NULL; size_t bufSiz = 0; char inputBuf[PAGESIZE]; FILE *in; if (argc < 2) { printf("Usage: %s filename\n", argv[0]); return 0; } in = fopen(argv[1], "r"); if (in) { /** * Read a page at a time until reaching the end of the file */ while (fgets(inputBuf, sizeof inputBuf, in) != NULL) { /** * Extend the dynamic buffer by the length of the string * in the input buffer */ tmp = realloc(buf, bufSiz + strlen(inputBuf) + 1); if (tmp) { /** * Add to the contents of the dynamic buffer */ buf = tmp; buf[bufSiz] = 0; strcat(buf, inputBuf); bufSiz += strlen(inputBuf) + 1; } else { printf("Unable to extend dynamic buffer: releasing allocated memory\n"); free(buf); buf = NULL; break; } } if (feof(in)) printf("Reached the end of input file %s\n", argv[1]); else if (ferror(in)) printf("Error while reading input file %s\n", argv[1]); if (buf) { printf("File contents:\n%s\n", buf); printf("Read %lu characters from %s\n", (unsigned long) strlen(buf), argv[1]); } free(buf); fclose(in); } else { printf("Unable to open input file %s\n", argv[1]); } return 0; } 

There are flaws with this approach; firstly, if there is not enough memory to store the contents of the file, you will not recognize it immediately. In addition, realloc () is relatively expensive to call, so you do not want your page sizes to be too small.

However, this avoids the use of fstat () or fseek () / ftell () to figure out how large the file is.

0
source

All Articles