Check if a fstream is either a file or directory

MacFreek picture MacFreek · Mar 27, 2015 · Viewed 7.7k times · Source

I'm using C++ fstream to read a config file.

#include <fstream>
std::ifstream my_file(my_filename);

Right now, if I pass the path of a directory, it silently ignores this. E.g. my_file.good() returns true, even if my_filename is a directory. Since this is unintended input for my program, I like to check for it, and throw an exception.

How do I check if a just opened fstream is a regular file, directory or stream?

I can't seem to find a way to either:

  • get the file descriptor from a given ifstream.
  • use some other mechanism to find this info in the ifstream.

In some forum discussion it was suggested that neither is possible because this is OS-dependant, and thus could never be part of the fstream C++ standard.

The only alternative I can think of is to rewrite my code to get rid of ifstream altogether and resort to the C-method of a file descriptor (*fp), along with fstat():

#include <stdio.h>
#include <sys/stat.h>
FILE *fp = fopen(my_filename.c_str(), "r");
// skip code to check if fp is not NULL, and if fstat() returns != -1
struct stat fileInfo;
fstat(fileno(fp), &fileInfo);
if (!S_ISREG(fileInfo.st_mode)) {
    fclose(fp);
    throw std::invalid_argument(std::string("Not a regular file ") + my_filename);
}

I prefer fstream. Hence, my question.

Answer

PSkocik picture PSkocik · Mar 27, 2015
void assertGoodFile(const char* fileName) {
   ifstream fileOrDir(fileName);
   //This will set the fail bit if fileName is a directory (or do nothing if it is already set  
   fileOrDir.seekg(0, ios::end);
   if( !fileOrDir.good()) {
      throw BadFile();
   };
}