14

In a project I have to do in C89 standard I have to check if a file exists. How do I do this?

I thought of using

FILE *file;
if ((file = fopen(fname, "r")) == NULL)
{
  printf("file doesn't exists");
}
return 0;

but I think there can be more cases then file doesn't exists that will do fopen == NULL.

How do I do this? I prefer not using includes rather then .

The GiG
  • 2,571
  • 2
  • 28
  • 29
  • 1
    if `fopen()` fails (i.e. returns `0`) you don't have to (can't!) close the file handle. You'd have to do it if successful. – Mario Apr 21 '11 at 14:17
  • 1
    I don't think there's a better way in the C89 standard. If you allow POSIX or other standards, see http://stackoverflow.com/questions/230062/whats-the-best-way-to-check-if-a-file-exists-in-c-cross-platform – interjay Apr 21 '11 at 14:17

5 Answers5

14

If you can't use stat() in your environment (which is definitely the better approach), just evaluate errno. Don't forget to include errno.h.

FILE *file;
if ((file = fopen(fname, "r")) == NULL) {
  if (errno == ENOENT) {
    printf("File doesn't exist");
  } else {
    // Check for other errors too, like EACCES and EISDIR
    printf("Some other error occured");
  }
} else {
  fclose(file);
}
return 0;

Edit: forgot to wrap fclose into a else

onitake
  • 1,369
  • 7
  • 14
  • -1 for ENOENT, `ENOENT` is not part of the standard C89 like the OP asked, its implementation defined and does not guarantee to exists. C89: "Additional macro definitions, beginning with E and a digit or E and an upper-case letter, may also be specified by the implementation." – Wiz Jun 02 '11 at 05:45
  • You are right, this isn't in the standard (and with good reason I guess). If the code should be 100% portable to all C89 implementations, this is not the right way to do it. On the other hand, support for ENOENT is widely available, so it's generally not a bad idea to use the above approach. Unless your platform is a very special one of course (embedded system, etc.). You can also simply bail out if fopen returns -1 and ignore the specific error, like in the example given in the question. – onitake Jun 24 '11 at 20:20
  • +1 for `ENOENT`. It's in the POSIX standard, and it's a much better approach than using `stat` as that may lead to race conditions and security problems. – Fred Foo May 20 '12 at 20:09
  • 2
    Why is `stat()` a better approach that `access()` with `F_OK`? – einpoklum Jun 10 '14 at 13:06
3

It's impossible to check existence for certain in pure ISO standard C. There's no really good portable way to determine whether a named file exists; you'll probably have to resort to system-specific methods.

Sadique
  • 22,572
  • 7
  • 65
  • 91
2

Do you really want to access the file? A check is usually better with the access(filename,F_OK)==0 from <unistd.h> and is a pretty wide standard, I think.

a stone arachnid
  • 1,272
  • 1
  • 15
  • 27
k9dog
  • 31
  • 4
2

This isn't a portable thing, so I'll give you OS-specific calls.

In Windows you use GetFileAttributes and check for a -1 return (INVALID_HANDLE or something like that).

In Linux, you have fstat to do this.

Most of the time however, I just do the file opening trick to test, or just go ahead and use the file and check for exceptions (C++/C#).

Blindy
  • 65,249
  • 10
  • 91
  • 131
1

I guess this has more to do with system environment (such as POSIX or BSD) than with which version of C language you're using.

In POSIX there is a stat() syscall that will give you information about a file, even if you cannot read it. However, if the file is in path that you have no access permissions to it's always going to fail regardless of whether the file exists.

If you have no access to the path then it should never be possible to look on files contained.

che
  • 12,097
  • 7
  • 42
  • 71