Jump to content
  • Advertisement
Sign in to follow this  
deadimp

C++ Simple Directory Listing Function - Sample Included

This topic is 4839 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

This is a small function for directory indexing that I made because a) I am about to make a resource manager b) I was somewhat bored. The "ScanDir()" function is my own version of the "scandir()" function, mainly because my compiler didn't have it. Code: "dir_funcs.h"
#ifndef DIR_FUNCS_H
 #define DIR_FUNCS_H

#include <vector>
 using std::vector;

enum DIRTYPE { DT_DIR=0x00, DT_FILE=0x01 };

struct DIR_ITEM {
 char name[FILENAME_MAX];
 DIRTYPE type;
 size_t size;
};
#define DIR_LIST vector<DIR_ITEM>
//Sort Modes
 #define DSM_DEF 0x00
 #define DSM_ASC 0x00
 #define DSM_DESC 0x01
 #define DSM_NAME 0x00
 #define DSM_SIZE 0x02
extern int DSORT_MODE;
//Whether to sort directories in their own part or with the group
extern bool DSORT_INCLUDE_DIR;
extern bool DSORT_CASE; //Whether to care about casing or not

bool ScanDir(char *dname,DIR_LIST *pOut,bool doSize=false,bool doSort=false,bool includeAll=false);

struct FS_FORMAT {
 float size;
 int level;
};
extern char FS_TYPE[][3];
extern long FS_LEVELS;
extern size_t FS_LIMIT;

void fsize_format(size_t bytes,FS_FORMAT *out);

#endif //DIR_FUNCS_H



"dir_funcs.cpp"
#include <iostream.h>
#include <fstream.h>
#include <dirent.h>
 #include <sys/stat.h>
#include <math.h>
#include <algorithm>

#include "dir_funcs.h"

int DSORT_MODE=DSM_DEF;
//Whether to sort directories in their own part or with the group
bool DSORT_INCLUDE_DIR=false;
bool DSORT_CASE=false; //Whether to care about casing or not

//Operator function for sortings
bool operator< (const DIR_ITEM &lhs,const DIR_ITEM &rhs) {
 bool out;
 if (lhs.type==rhs.type || DSORT_INCLUDE_DIR) {
  if (DSORT_MODE & DSM_SIZE) out=(lhs.size > rhs.size); //Reverse size order
  else {
   if (DSORT_CASE) out=(strcmp(lhs.name,rhs.name)<0);
   else out=(strcasecmp(lhs.name,rhs.name)<0);
  }
 }
 else out=(lhs.type < rhs.type);
 if (DSORT_MODE & DSM_DESC) return !out;
 else return out;
}

bool ScanDir(char *dname,DIR_LIST *pOut,bool doSize,bool doSort,bool includeAll) {
 if (pOut==NULL) return false;
 DIR *dir=opendir(dname);
 if (dir==NULL) return false;
 DIR_LIST &vOut=*pOut; //Lazy be I
 dirent *dfile;
 struct stat dinfo; //Make sure it knows its a variable, not a function!
 char *fname;
 size_t index;
 fstream file;
 //Pre-compute and allocate size, or just make it completely dynamic?
 while ((dfile=readdir(dir))!=NULL) {
  fname=dfile->d_name;
  if (!includeAll) {
   if (strcmp(fname,".")==0 || strcmp(fname,"..")==0) continue;
  }
  if (stat(fname,&dinfo)==0) {
   index=vOut.size();
   vOut.push_back(DIR_ITEM()); //I shudder at how inefficient this is...
   memcpy(vOut[index].name,fname,strlen(fname)+1); //Copy it
   vOut[index].size=0;
   //It is all right
   if (S_ISDIR(dinfo.st_mode)) {
    //It's a directory
    vOut[index].type=DT_DIR;
   }
   else {
    //File
    vOut[index].type=DT_FILE;
    if (doSize) {
     file.open(fname,ios::in | ios::binary);
     long fbeg=file.tellg();
     file.seekg(0,ios::end);
     long fend=file.tellg();
     file.close();
     vOut[index].size=fend-fbeg;
    }
   }
  }
  //End of error checking
 }
 if (doSort) sort(vOut.begin(),vOut.end());
 //End of while
 return true;
}

char FS_TYPE[][3]={"B","KB","MB","GB","TB"};
long FS_LEVELS=4;
size_t FS_LIMIT=512;

void fsize_format(size_t bytes,FS_FORMAT *out) {
 out->size=(float)bytes;
 out->level=0;
 while (out->size>=FS_LIMIT) {
  out->size/=1024;
  out->level++;
  if (out->level>=FS_LEVELS) break;
 }
}



And here is a simple example to go along with it: "main.cpp"
#include <iostream.h>

#include "dir_funcs.h"

int main() {
 DIR_LIST files;
 FS_FORMAT fsize; //For formatting the file size
 //Scan the current directory, getting file sizes, sorting, but not including everything
 ScanDir(".",&files,true,true);
 //Sort the files
 for (long i=0;i<files.size();i++) {
  cout << files.name;
  if (files.type==DT_DIR) {
   cout << " [DIR]";
  }
  else {
   cout << " ";
   //Format size
   fsize_format(files.size,&fsize);
   cout << fsize.size;
   if (fsize.level>0) cout << " " << FS_TYPE[fsize.level];
  }
  cout << "\n";
 }
 cout << "\n";
 system("PAUSE");
 return 0;
}



Please note that this was compiled using Dev-C++ 4.9.9.1 in Windows XP, so I'm not sure of compatability. One of the main concerns I have with this is its usage of std::vector. It's not that I don't like it, it's just that the code seems rather inefficient. However, since I didn't know of any simple way of counting the number of entries in a directory, I simply went with the vector for more simplicity. Does anybody know which way would be faster? The constant memory allocation/deallocation, or pre-scanning and rewinding?

Share this post


Link to post
Share on other sites
Advertisement
Umm... I was somewhat bored at the time, plus I wanted how to do the basic directory listing too.
As for the efficiency, I'm not sure it will matter too much when it comes right down to it.
Thanks.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!