Win32 list all files in i directory

Started by
5 comments, last by Shannon Barber 19 years, 6 months ago
I'm trying to list all files in a directory. When you use FindFirstFile and FindNextFile you also get all subdirectories and I only want the files. The code I have so far is.
#include <windows.h>
#include <string>
#include <iostream>
#include <vector>
using namespace std;

typedef vector< WIN32_FIND_DATA > FileList;

bool IsDirectory( const std::string& path )
{
	return GetFileAttributes( path.c_str() ) & FILE_ATTRIBUTE_DIRECTORY;
}

int main( int argc, char* argv[] )
{
	if( argc < 2 ) return -1;
	string dirSpec = argv[1];

	FileList files;

	cout << "Target directory is " << dirSpec << endl;
	dirSpec += "\\*";

	WIN32_FIND_DATA FindFileData;
	HANDLE hFind = FindFirstFile( dirSpec.c_str(), &FindFileData );

	if( hFind == INVALID_HANDLE_VALUE ) 
	{
		cout << "Invalid file handle. Error is " << GetLastError() << endl;
		return -1;
	}
	else
	{
		if( !IsDirectory( FindFileData.cFileName ) )
		{
			files.push_back( FindFileData );
		}
		while( FindNextFile( hFind, &FindFileData ) )
		{
			if( !IsDirectory( FindFileData.cFileName ) )
			{
				files.push_back( FindFileData );
			}
		}

		DWORD dwError = GetLastError();
		if( dwError == ERROR_NO_MORE_FILES )
		{
			FindClose( hFind );
		}
		else
		{
			cout << "FindNextFile error. Error is " << dwError << endl;
			return -1;
		}
	}

	for( int i = 0; i < files.size(); ++i )
	{
		cout << files.cFileName << '\n';
	}
	cout << endl;
	return 0;
}
The problem is that IsDirectory returns true for everything FindFirstFile/FindNextFile finds. If I call the function with just the path it works as it should.
Advertisement
bool IsDirectory(const WIN32_FIND_DATA &findData){  return (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);}
Don't forget FindClose! Otherwise you'll get a resource leak.

Fruny: Ftagn! Ia! Ia! std::time_put_byname! Mglui naflftagn std::codecvt eY'ha-nthlei!,char,mbstate_t>

Thanks Oluseyi, why didn't my code work? Because if I called it like IsDirectory( "c:\\program" ) it would return true, and IsDirectory( "c:\\log.txt" ) returned false.
Do I need FindClose somewhere else the where I have it now? Most of the code is from MSDN. I have just removed some printf's and changed the char[] to a string.
Sorry, my bad. I looked to shortly and didn't see the FindClose is already there.

Your code did work too, but since you're using FindFirstFile this will give you the file attributes already, so there's no need to retrieve them a second time.

Fruny: Ftagn! Ia! Ia! std::time_put_byname! Mglui naflftagn std::codecvt eY'ha-nthlei!,char,mbstate_t>

Quote:Original post by Eriond
Thanks Oluseyi, why didn't my code work?
An error could have occured on GetFileAttributes(), which can only be detected by calling GetLastError(). Your IsDirectory() should have looked like this:
bool IsDirectory(const std::string & file){  DWORD attr = GetFileAttributes(file.c_str());  if(GetLastError() != 0) return false;  return attr & FILE_ATTRIBUTE_DIRECTORY;}
boost:directory_iterator
- The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara

This topic is closed to new replies.

Advertisement