Click here to Skip to main content
6,291,722 members and growing! (12,979 online)
Email Password   helpLost your password?
Desktop Development » Files and Folders » General     Intermediate

Win32 file name iteration STL way

By bektek

This simple class shows how to iterate file names by using STL iterator interface.
VC7.1Win2K, WinXP, Visual Studio, MFC, STL, Dev
Posted:21 Nov 2004
Views:68,066
Bookmarked:37 times
Announcements
Loading...
 
Search    
Advanced Search
printPrint   Broken Article?Report       add Share
  Discuss Discuss   Recommend Article Email
18 votes for this article.
Popularity: 6.09 Rating: 4.85 out of 5
1 vote, 5.6%
1

2

3
2 votes, 11.1%
4
15 votes, 83.3%
5

Introduction

Several times I worked with file names, I usually used Win32 API such as ::FindFirstFile.. But it turns out that it's so boring work. Finally, I realized I can use STL's great feature, iterator, to handle file name iteration. That's why I made a simple STL iterator class for file name iteration.

Usage

win32_file_iterator itBegin("c:\\*.*"), itEnd;
std::copy(itBegin, itEnd, ostream_iterator<std::string>(cout, "\n"));

The code above shows the simplest way to use the class. Actually, you can use almost all of STL algorithm, I think..

win32_file_iterator itBegin("c:\\*.*"), itEnd;
std::vector<std::string> vec(itBegin, itEnd);

You also can fill the STL container by using the constructor that takes begin iterator and end iterator.

Actually, win32_file_iterator class' constructor takes three parameters. The first one is the filter string that is for calling ::FindFirstFile function. Second one is the flag that specifies whether dereferenced path is full path or not. For example, if it's true, the returned path string is c:\test\aa.txt, otherwise it'll be aa.txt only. The last parameter is the other flags which specify file attribute. For simplicity, I used Win32 API's FILE_ATTRIBUTE_XXX flags..

If you want to get only directory names, and which is full path, the code will look like this:

win32_file_iterator itBegin("c:\\*", true, FILE_ATTRIBUTE_DIRECTORY);

So easy, huh?

Source

#include <windows.h>

#include <iterator>

#include <string>


class win32_file_iterator : 
 public std::iterator<std::input_iterator_tag, std::string>
{
private:

 class internal_handle_data{
 public:
  internal_handle_data():_h(NULL), _ref(0){}
  void setHandle(HANDLE handle){ _h = handle; }
  HANDLE getHandle(){ return _h; }
  void incRef(){ _ref++; }
  unsigned decRef(){ return --_ref; }
  operator HANDLE(){ return _h; }

 private:
  HANDLE _h;
  unsigned _ref;
 };


public:

 win32_file_iterator(std::string strfilter, bool bFullPath = false, 
   int flag = FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_NORMAL|FILE_ATTRIBUTE_DIRECTORY):
   _bEnd(false), _bFullPath(bFullPath), _flag(flag){
        HANDLE h = ::FindFirstFile(strfilter.c_str(), &_wfd);
  _handle.setHandle(h);
  if(h == INVALID_HANDLE_VALUE){
   _bEnd = true;
  }else{
   _handle.incRef();
   std::string::size_type n1 = strfilter.find_last_of("\\");
   _strroot = strfilter.substr(0,n1+1);
   _chkvalid(_wfd);
  }
 }

 win32_file_iterator():_bEnd(true){}

 win32_file_iterator(win32_file_iterator& rhs){
  
  _handle = rhs._handle;
  _handle.incRef();
  _flag = rhs._flag;
  _bFullPath = rhs._bFullPath;
  _bEnd = rhs._bEnd;
  _wfd = rhs._wfd;
  _strfname = rhs._strfname;
  _strroot = rhs._strroot;  
 }

 ~win32_file_iterator(){
  if(_handle.decRef() == 0 && _handle.getHandle() != NULL ){
   FindClose(_handle);
  }
  
 }

 reference operator*(){
  return _strfname;
 }

 bool operator==(const win32_file_iterator& rhs) const{
  return (_bEnd == rhs._bEnd);
 }

 bool operator!=(const win32_file_iterator& rhs) const{
  return (_bEnd != rhs._bEnd);
 }


 win32_file_iterator& operator++(){
  _findnext();
  return *this;
 }

 win32_file_iterator& operator++(int){
  _findnext();
  return *this;
 }

private:

 void _findnext(){
  BOOL b = ::FindNextFile(_handle, &_wfd);
  if(b){
   _chkvalid(_wfd);
  }else{
   _bEnd = true;
  }
 }

 void _chkvalid(WIN32_FIND_DATA& _wfd){
  if(_wfd.dwFileAttributes & _flag){
   _getval(_wfd);
  }
  else{
   _findnext();
  }
 }

 void _getval(WIN32_FIND_DATA& wfd){
  if(_bFullPath)
   _strfname = _strroot+ wfd.cFileName;
  else
   _strfname = wfd.cFileName;
 }


private:
 int _flag;
 bool _bFullPath;
 bool _bEnd;
 internal_handle_data _handle;
 WIN32_FIND_DATA _wfd;
 std::string _strroot;
 std::string _strfname;
};

Comment

The code might have many terrible bugs. But what I want was to show the way we can use STL like iteration to find filenames. I wish it'll help you. You can use this code in whatever ways you want, comments are welcome..

And also check out boost::filesystem library.. it's well-written but a little bit heavy. It needs an additional DLL, I suppose.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

bektek


Member
study, study, That's all I can say Smile
Location: United States United States

Other popular Files and Folders articles:

Article Top
You must Sign In to use this message board.
FAQ FAQ 
 
Noise Tolerance  Layout  Per page   
 Msgs 1 to 25 of 32 (Total in Forum: 32) (Refresh)FirstPrevNext
Generaltype "reference" ? PinmemberGerald E.0:39 25 Aug '05  
GeneralRe: type "reference" ? Pinmembermvalle4:23 9 Sep '05  
AnswerRe: type "reference"? PinmemberHans-Martin Jensen2:37 13 May '06  
GeneralSeveral issues with the published code Pinmember.:fl0yd:.5:33 2 Dec '04  
GeneralBrilliant PinmemberRobert Bielik22:03 24 Nov '04  
GeneralSuggestion PinmemberRobert Bielik22:07 24 Nov '04  
GeneralRe: Suggestion Pinmemberbektek9:15 25 Nov '04  
GeneralOne very minor comment Pinmembersdoyle7:47 24 Nov '04  
GeneralRe: One very minor comment Pinmemberbektek11:44 24 Nov '04  
GeneralStlSoft and WinSTL PinmemberNeville Franks0:18 24 Nov '04  
GeneralRe: StlSoft and WinSTL Pinmemberbektek0:20 24 Nov '04  
GeneralRe: StlSoft and WinSTL PinmemberRobert Bielik10:14 25 Nov '04  
GeneralRe: StlSoft and WinSTL PinmemberNeville Franks10:23 25 Nov '04  
GeneralRe: StlSoft and WinSTL Pinmember.:fl0yd:.6:01 2 Dec '04  
GeneralRe: StlSoft and WinSTL PinmemberRobert Bielik20:59 2 Dec '04  
GeneralLooks nice. Pinmemberrtw170118:16 23 Nov '04  
GeneralTake a look at boost::filesystem PinmemberPhan Manh Dan23:33 22 Nov '04  
GeneralRe: Take a look at boost::filesystem Pinmemberbektek10:16 23 Nov '04  
GeneralRe: Take a look at boost::filesystem Pinmemberoccam6:37 26 Nov '04  
GeneralRe: Take a look at boost::filesystem PinsussAnonymous23:09 26 Nov '04  
GeneralRe: Take a look at boost::filesystem Pinmemberoccam2:07 27 Nov '04  
GeneralRe: Take a look at boost::filesystem Pinmembernastanet23:24 28 Nov '04  
GeneralRe: Take a look at boost::filesystem Pinmemberbektek1:17 29 Nov '04  
GeneralRe: Take a look at boost::filesystem Pinmembernastanet1:36 29 Nov '04  
GeneralCould you explain? PinmemberWREY6:28 22 Nov '04  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 21 Nov 2004
Editor: Smitha Vijayan
Copyright 2004 by bektek
Everything else Copyright © CodeProject, 1999-2009
Web13 | Advertise on the Code Project