0

I make a function to check if the text file is empty or not . I use fseek and ftell to check , but the problem is if the first line is a '\n' and next line is EOF then ftell will return 2 but not 0 . I want to check if the file actually empty or not but i cant think if there is a way to check the situation above . Please help . Here is my code

void fileReader(FILE *file,char filePath[]){
char output[100];
file = fopen(filePath,"r");
printf("Content of file : ");
fseek(file, 0, SEEK_END); 
printf("%d",ftell(file));
if(ftell(file)==0){
    printf("\nthere is nothing here");
}
else{  
    do{
        printf("%s", output);  
    }while (fscanf(file, "%s", output) != EOF);
} 
fclose(file);
}
phuonglinh
  • 23
  • 4
  • 1
    Does this help? https://stackoverflow.com/questions/49121638/use-ftell-to-find-the-file-size – Amal K May 31 '20 at 07:04
  • 1
    In the case you described, `ftell()` should return 1, not 0. Anyway, the question is how you define "empty". Is a file with a `\n` and nothing else - empty? What about a million newlines? What about spaces and newlines? If you're willing to accept files with such contents as "empty", you need to read the contents of the file and match it up against your criteria of what's empty. – einpoklum May 31 '20 at 07:18
  • You invoke *Undefined Behavior* in your code using the `"%d"` conversion specifier to print a `long int`. Any mismatch between type and conversion specifier will invoke undefined behavior. It should be `"%ld"` to accompany the additional 4bytes. See [C11 Standard - 7.21.6.1 The fprintf function(p9)](http://port70.net/~nsz/c/c11/n1570.html#7.21.6.1p9) – David C. Rankin May 31 '20 at 07:35
  • yes i consider the file contain only space, tab, newline etc is empty , but i don't know how to check it – phuonglinh May 31 '20 at 07:40
  • If you just want to know whether the file contains something not *whitespace*, then open the file and `char buf[1024]; if (fscanf (file, "%s", buf) == 1) { /* file contains non-whitespace */ }`. You can check file size first with `ftell()` or `stat`, then check with `fscanf`. – David C. Rankin May 31 '20 at 07:43
  • 1
    @bruno yes thank you i understand now – phuonglinh May 31 '20 at 08:15

1 Answers1

1

but the problem is if the first line is a '\n' and next line is EOF then ftell will return 2 but not 0

you do not want to know if a file is empty meaning its size is 0, but if the file contain something else that space, tab, newline etc, in that case the size is not enough. One way to do that can be :

#include <stdio.h>

int main(int argc, char ** argv)
{
  FILE * fp;

  if (argc != 2)
    fprintf(stderr, "Usage %s <file>\n", *argv);
  else if ((fp = fopen(argv[1], "r")) == NULL)
    perror("cannot read file");
  else {
    char c;

    switch (fscanf(fp, " %c", &c)) { /* note the space before % */
    case EOF:
      puts("empty or only spaces");
      break;
    case 1:
      puts("non empty");
      break;
    default:
      perror("cannot read file");
      break;
    }
    fclose(fp);
  }

  return 0;
}

In fscanf(fp, " %c", &c) the space before % ask to bypass whitespaces (space, tab, newline ...)

Compilation and executions:

pi@raspberrypi:/tmp $ gcc -Wall c.c
pi@raspberrypi:/tmp $ ./a.out /dev/null
empty or only spaces
pi@raspberrypi:/tmp $ echo > e
pi@raspberrypi:/tmp $ wc -c e
1 e
pi@raspberrypi:/tmp $ ./a.out e
empty or only spaces
pi@raspberrypi:/tmp $ echo "   " > e
pi@raspberrypi:/tmp $ echo "   " >> e
pi@raspberrypi:/tmp $ wc -c e
8 e
pi@raspberrypi:/tmp $ ./a.out e
empty or only spaces
pi@raspberrypi:/tmp $ echo "a" >> e
pi@raspberrypi:/tmp $ cat e


a
pi@raspberrypi:/tmp $ ./a.out e
non empty
pi@raspberrypi:/tmp $ 
pi@raspberrypi:/tmp $ chmod -r e
pi@raspberrypi:/tmp $ ./a.out e
cannot read file: Permission denied
pi@raspberrypi:/tmp $ ./a.out
Usage ./a.out <file>
pi@raspberrypi:/tmp $ 
bruno
  • 32,421
  • 7
  • 25
  • 37
  • @DavidC.Rankin no, the format I use is not `"%c"` but `" %c"` and the space before `%` changes all asking `fscanf` to bypass the 'spaces' – bruno May 31 '20 at 07:52
  • 1
    Gotcha... That makes more sense. (I'm due for a glasses update...) – David C. Rankin May 31 '20 at 08:00
  • @DavidC.Rankin in a way when `"%s"` there is an implicit space and  `scanf` family does like `" %s"` – bruno May 31 '20 at 08:01
  • 1
    Yes, that's why `"%s"` was my first thought, but `" %c"` will do the same thing. (you just can't be blind to the space `:)` – David C. Rankin May 31 '20 at 08:02