I use fopen to check if a file or directory exists:
#include <stdio.h>
#include <string>
void file_exists(std::string file) {
FILE* fp = NULL;
fp = fopen( file.c_str(), "rb" );
if( fp == NULL ) {
std::cout << "File = " << file << " does not exist!" << std::endl;
exit(0);
}
fclose(fp);
}
On Ubuntu linux this works fine both for files and directories. But on
windows vista 64 using visual studio 2008 it only works for files. If 'file'
is eg:
"c:\test" // I have also tried with ''c:/test"
then I get the message:
File = c:/test/ does not exist!
which means that fp is NULL. Why does it work on linux for directories but
not on windows?
Because in Linux or Unix the directories are actually files. On
Windows there's a DOS file attribute or so, the file system attribute.
So you can't open directories with fopen on Windows. On Windows,
getting the directory is null, because as a file it's null. (I could
be wrong, also it could be set up to return an open file handle if you
use your own API routines around the Windows API.) On Unix, getting
the directory is a file, with a list of the files in the directory.
On some Unix machines the directories have user and group attributes
so the directory access could be made null on Unix also.
In C++ it's called ::fopen(const char*, ...);, let's see, the second
argument to fopen is the collected open flags so it could be a byte,
probably it is a default numeric type the integer: int.
fopen(const char*, const char*);
Why it's ::fopen instead of fopen() is that then other C++ programs in
the same code could use fopen instead of ::fopen. In C++ it's
standard that ::fopen() is the same as fopen().
The "fopen" is for "File Open", many of the file access routines begin
with f in the file "stdio.h": fopen, fclose, fread, fwrite, yet not
fsize because that is often a platform-dependent function, so to get
the file size in standard C you open the file, use fseek to seek to
the end, and get the offset with ftell, that's the same as fsize, but
some compiler facility import libraries have. Then, in C++, instead
of "stdio.h", it's <cstdio>, to then use the ::fopen functions in C+
+. They left the C standard import libraries for standard libraries
in C++, some of them.
Of course, in the platform libraries, for using files, sometimes it's
better to use memory mapping with the virtual memory machinery more
directly, "mmap.h" or on Windows OpenFileForViewMapping or whatever.
Also for example looking through the compiler's include directory
inc/, platforms have vectorization intrinsic support, "dvec.h".
Working through directories is called "file tree walk".
http://linux.die.net/man/3/ftw
To implement directory traversal in Windows, there is FindFirstFile/
FindNextFile with the struct FILEINFO so it would be good, in C++, to
implement a class to encapsulate that regular behavior as an iterator
over the directory contents by file type and offset. (Includes ., ..,
Windows FindtFirstFile and FindNextFile's results are the directory
links.)
class directory
{
directory(string)
iterator& begin()
iterator& end()
}
There is time involved with that for generating the iterator adaptors
to use the system APIs to get the directories under a directory. That
is where, using the system APIs to list the directory contents returns
iterators over various kinds of objects: file, directories, links,
any file system directory API object (handle), the system can make the
list whatever it wants.
Then just have something like
for_each_file(string pattern)
to implement that on Linux and Windows, it's separate for each,
because something like the command "ls" on Linux returns the variety
of output of the standard systems, also Windows has an advanced file
system with the shell namespace.
http://www.ddj.com/windows/184416631
That is an article discussing adapting Windows enumerator APIs to STL
iterator APIs.
Ross F.