4

I have a text file, which has random amount of characters, numbers, spaces and new lines. I'm trying to figure out how to find the "length" of this file. For example: if the text file contains "This is an example." the lenght should be 19. I tried using both sizeof(text_file) and strlen(text_file), but they don't give me the desired output.

What I also tried was this:

 void test(FILE *f)
 {
     int i;
     i=0;
     char ch;

     while( ( ch = fgetc(f) ) != EOF ) {
         printf("%c",ch);    /*This is just here to check what the file contains*/
  
         if(ch!='\0') {
             i=i+1;
         }
     }

     printf("------------------\n");
     printf("The length of the file is\n");
     printf("%d",i);   /*For some reason my length is always +1 what it actually should be*\
}

Is there an easier way to do this and why does the code above always give +1? I guess there is something wrong with the if statement, but I don't know what.

Any help is really appreciated thanks in advance.

klutt
  • 30,332
  • 17
  • 55
  • 95
roneboy
  • 73
  • 1
  • 1
  • 5
  • 3
    `fseek(f, 0, SEEK_END); size_t length = ftell(f);` should to the job. –  Jan 12 '14 at 11:31
  • 1
    [man fstat](http://linux.die.net/man/2/fstat) – fvu Jan 12 '14 at 11:33
  • fseek and ftell does the trick thanks! – roneboy Jan 12 '14 at 11:57
  • 1
    I don't think this counts as a duplicate. The other answer asked for a file in general (for which the fseek / ftell is not a portable solution), whereas this specifically asked for text files. – CoffeeTableEspresso Nov 15 '18 at 00:53
  • Voting to reopen - I strongly agree with the observations made in @CoffeeTableEspresso comments. Specifically when using `ftell()` for _binary_ streams, the value returned does represent the number of characters from the beginning of the file. However, when using it for a ***text*** stream, the value is not necessarily a meaningful measure. This question is clearly asking for help on how to determine the size of a ***text*** file. – ryyker Nov 17 '22 at 14:32

2 Answers2

3

As others have already explained, there are better ways to determine a file size.

The reason that your code does not give the expected result is probably that your file contains a trailing newline character \n which is counted as well:

This is an example.\n

are 20 characters, not 19.

And note that you should declare int ch, not char ch for the EOF-check to work properly, compare fgetc, checking EOF.

Community
  • 1
  • 1
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
2

As for the size you can do this:

 size_t pos = ftell(f);    // Current position
 fseek(f, 0, SEEK_END);    // Go to end
 size_t length = ftell(f); // read the position which is the size
 fseek(f, pos, SEEK_SET);  // restore original position

If you don't care about the position, you can of course omit resetting the current filepointer.

Devolus
  • 21,661
  • 13
  • 66
  • 113
  • 3
    Note that this can only be relied on with files opened in binary mode, and even then there may be [other potential issues](https://www.securecoding.cert.org/confluence/display/seccode/FIO19-C.+Do+not+use+fseek%28%29+and+ftell%28%29+to+compute+the+size+of+a+regular+file). Though it's a good quick solution, unfortunately extra libraries are needed to do this properly (i.e. abstractions such as `Boost.Filesystem`, Qt's `QFile`, or simply accessing the OS directly with [`stat`](http://pubs.opengroup.org/onlinepubs/009695399/functions/stat.html).) You probably know this, but it's worth noting. – John Chadwick Jan 12 '14 at 11:38
  • For clarity it would be an improvement here to edit post to include a caution that this approach limited to files opened into binary streams. eg, I believe the size measurement of a text file opened into a binary stream, eg. with `FILE *fp = fopen(filespec, "rb");` will be accurate with this method, however it will not be accurate for the same file opened into a text stream, eg: ``FILE *fp = fopen(filespec, "r");`` – ryyker Nov 17 '22 at 18:00