reading a directory in C++ in portable way
I have a requirement as follows. I have a directory for eg i have /tmp/myFolder
开发者_StackOverflow社区Under "myFolder" i have files whose names as below
myFile-N001.txt
myFile-N002.txt
myFile-N003.txt
in my application while writing to a file i should write to largest number file in /tmp/myFolder, for eg in above case i should write to myFile-N003.txt.
The above should be achieved in C++ and in portable way preferably in POSIX way.
Can any one provide simple example on how we can achive this in C++.
Thanks
If you are happy enough to:
- work only on POSIX
- You know the pattern you are looking for
You can use the glob()
function in POSIX to get the list.
You can then use std::max with a custom comparison on the result set with your iterator range being globres.gl_pathv[0], globres.gl_pathv[globres.gl_pathc] and a comparison being something like:
bool strless(const char* str1, const char* str2 )
{
return strcmp( str1, str2 ) < 0;
}
although there is most likely something already that does that
The start of the "man" page for glob:
#include <glob.h>
int glob(const char *pattern, int flags,
int (*errfunc) (const char *epath, int eerrno),
glob_t *pglob);
void globfree(glob_t *pglob);
DESCRIPTION
The glob()
function searches for all the pathnames matching pattern according to the rules used by the shell (see glob
(7)). No tilde expansion or parameter substitution
is done; if you want these, use wordexp
(3).
The globfree()
function frees the dynamically allocated storage from an earlier call to glob()
.
The results of a glob()
call are stored in the structure pointed to by pglob. This structure is of type glob_t
(declared in <glob.h>
) and includes the following elements
defined by POSIX.2 (more may be present as an extension):
typedef struct
{
size_t gl_pathc; /* Count of paths matched so far */
char **gl_pathv; /* List of matched pathnames. */
size_t gl_offs; /* Slots to reserve in gl_pathv. */
} glob_t;
There was a discussion in October 2004 about bringing glob into boost I don't think it ever got implemented:
There's code for retrieving the list of files from a directory in a POSIX-compliant way here.
You could build on that by sorting the resulting array and popping the last element off. That would be the file you want to find.
This is really two problems in one. I'd use Boost.Filesystem to portably iterate over the files and store them in a vector
with (untested)
std::string maxname;
unsigned maxnum = 0;
for (fs::path::iterator i(dir.begin()), end(dir.end()); i != end; ++i) {
std::string name = i->string();
unsigned num;
if (std::sscanf(name.c_str(), "myFile-N%u.txt", &num) == 1
&& num >= maxnum) {
maxnum = num;
maxname = name;
}
}
then check whether maxname
holds the empty string after the loop. If it doesn't, it holds the filename you want.
You can use boost::filesystem to achieve this.
精彩评论