Jump to content


Get list of files with *.dds


24 replies to this topic

#1 Phlex

    Member

  • Members
  • PipPip
  • 53 posts

Posted 04 May 2009 - 09:37 AM

Hey, I've been looking into populating an array of LPCSTR's with the file paths of all the .dds files in a particular folder (Media/LightProbes/). I've seen a number of methods that use the boost libraries file system but I'd rather stay away from boost for now.
The basic process would go like this


scan the folder
int numDDSFiles = 0;
for (each file, check dds)
numDDSFiles++;

LPCSTR DirectoryArrays[numDDSFiles];
for(int i = 0; i < numDDSFiles; i++)
{
DirectoryArrays[i] = "Media/LightProbes/" + fileName + "dds";
}


trouble is I don't know how to check how many files there are in a particular file that have a certain file extension, or how to get what that file name is. I'd be happy to use STL or Win32 library and am open to other methods, but as stated above would rather not use boost.

Thanks =)

#2 monjardin

    Senior Member

  • Members
  • PipPipPipPip
  • 1033 posts

Posted 04 May 2009 - 02:47 PM

File and Directory Enumeration
By Andreas Saurwein Franci Gonçalves

monjardin's JwN Meter (1,2,3,4,5,6):
|----|----|----|----|----|----|----|----|----|----|
*

#3 Phlex

    Member

  • Members
  • PipPip
  • 53 posts

Posted 05 May 2009 - 04:45 AM

hey monjardin, thanks for the reply. I'm having some trouble understanding how it works, and how to implement, I understand that under his given framework, I would add a filter for *.dds files where he says this:


You can implement simple filtering by filename (or extension) like this:

bool CheckUseFile(LPCTSTR, WIN32_FIND_DATA* pwfd)
{
return ::PathMatchSpec(pwfd->cFileName, _T("*.jpg"));
}


although much of the code that is presented in the download file seems very complicated and I'm finding it difficult to understand, is there not an easier way to go about it?

Thanks

#4 Reedbeta

    DevMaster Staff

  • Administrators
  • 5308 posts
  • LocationSanta Clara, CA

Posted 05 May 2009 - 05:05 AM

Do you just want to find files in a single folder (no sub-folders), or an entire tree (folders, its sub-folders, and their sub-folders, etc...)? For an entire tree, monjardin's link may be useful, but if you just want to look at a single folder, you can just use FindFirstFile and FindNextFile. You'd pass FindFirstFile a search string like "c:\myproject\*.dds", then run a loop calling FindNextFile until it returns false.
reedbeta.com - developer blog, OpenGL demos, and other projects

#5 Phlex

    Member

  • Members
  • PipPip
  • 53 posts

Posted 05 May 2009 - 05:20 AM

I'm just looking to find the files in a single folder, "Media/LightProbes/" and get just the names of the files with a .dds file extension.

#6 Reedbeta

    DevMaster Staff

  • Administrators
  • 5308 posts
  • LocationSanta Clara, CA

Posted 05 May 2009 - 05:26 AM

Then FindFirstFile and FindNextFile should be effective and pretty simple to use.
reedbeta.com - developer blog, OpenGL demos, and other projects

#7 Phlex

    Member

  • Members
  • PipPip
  • 53 posts

Posted 05 May 2009 - 06:10 AM

k thanks :)

#8 Phlex

    Member

  • Members
  • PipPip
  • 53 posts

Posted 05 May 2009 - 07:35 AM

Ok, I've tried implementing a simple one that just gets all the files in a directory, here's the code

HANDLE hHandle;
	WIN32_FIND_DATA* pData = NULL;
	std::vector<LPCSTR> Directories;

	hHandle = FindFirstFile("Media/LightProbes/", pData);

	BOOL bMoreFiles = TRUE;
	while(bMoreFiles == TRUE)
	{
		bMoreFiles = FindNextFile(hHandle, pData);
		if(bMoreFiles == TRUE)
		{
			Directories.push_back(LPCSTR(pData->cFileName));
		}
	}

but when I check the size of Directories and it is 0, I have checked in the file Media/LightProbes and there are 9 files there, what's happening?

#9 Goz

    Senior Member

  • Members
  • PipPipPipPip
  • 575 posts

Posted 05 May 2009 - 08:14 AM

Try this ...


HANDLE hHandle;

	WIN32_FIND_DATA* pData = NULL;

	std::vector<LPCSTR> Directories;


	hHandle = FindFirstFile("Media/LightProbes/*", pData);


	BOOL bMoreFiles = TRUE;

	while(bMoreFiles == TRUE)

	{

		bMoreFiles = FindNextFile(hHandle, pData);

		if(bMoreFiles == TRUE)

		{

			Directories.push_back(LPCSTR(pData->cFileName));

		}

	}

Edit: Heh ... the code block appears to get proper confused by a /* in a string ...

#10 Phlex

    Member

  • Members
  • PipPip
  • 53 posts

Posted 05 May 2009 - 08:55 AM

Hey, thanks for the reply, I'm getting a compile error that directs me to this in vector



bool _Buy(size_type _Capacity)
{ // allocate array with _Capacity elements
_Myfirst = 0, _Mylast = 0, _Myend = 0;
if (_Capacity == 0)
return (false);
else if (max_size() < _Capacity)
_Xlen(); // result too long
else
{ // nonempty array, allocate storage
_Myfirst = this->_Alval.allocate(_Capacity);
_Mylast = _Myfirst;
_Myend = _Myfirst + _Capacity;
}
return (true);
}

#11 Goz

    Senior Member

  • Members
  • PipPipPipPip
  • 575 posts

Posted 05 May 2009 - 09:34 AM

And what does the error tell you?

There is another bug though. An LPCSTR is a Long Pointer to a Constant STRing. Basically after you call FindNextFile the pData->cFileName is most probably de-allocated and freed. To fill your structure you should be copying the string to your own allocation (Which you, of course, need to free after you've used it).

So try this code ...


HANDLE hHandle;

WIN32_FIND_DATA* pData = NULL;

std::vector<TCHAR*> Directories;


hHandle = FindFirstFile("Media/LightProbes/*", pData);


BOOL bMoreFiles = TRUE;

while(bMoreFiles == TRUE)

{

	bMoreFiles = FindNextFile(hHandle, pData);

	if(bMoreFiles == TRUE)

	{

		const size_t strLen	= _tcslen( pData->cFileName ) + 1;

		TCHAR* pNewStr		= new TCHAR[strLen];

		_tcscpy_s( pNewStr, strLen, pData->cFileName );

		Directories.push_back( pNewStr );

	}

}


#12 Phlex

    Member

  • Members
  • PipPip
  • 53 posts

Posted 05 May 2009 - 09:41 AM

Hey, what includes and lib's do I need for _tcslen and _tcscpy_s?

#13 Goz

    Senior Member

  • Members
  • PipPipPipPip
  • 575 posts

Posted 05 May 2009 - 09:46 AM

you need to #include <tchar.h>

#14 Goz

    Senior Member

  • Members
  • PipPipPipPip
  • 575 posts

Posted 05 May 2009 - 09:47 AM

Its worth noting that all its doing is modifying the code so that it will work with UTF-8 or UTF-16 strings. You can easily change TCHAR to char and change _tcs* to str*

#15 Phlex

    Member

  • Members
  • PipPip
  • 53 posts

Posted 05 May 2009 - 09:49 AM

Got the same thing as before, with that section from vector and this:


First-chance exception at 0x7c902128 in RTHDRIBLEngine.exe: 0xC0000005: Access violation writing location 0x00000000.
Unhandled exception at 0x7c902128 in RTHDRIBLEngine.exe: 0xC0000005: Access violation writing location 0x00000000.

#16 Goz

    Senior Member

  • Members
  • PipPipPipPip
  • 575 posts

Posted 05 May 2009 - 09:54 AM

Oh yeah don't use a WIN32_FIND_DATA pointer unless you are prepared to allocate the memory for it. Basically you are telling FindFirstFile to fill memory at address 0 (NULL) and that raises an access violation (0xc0000005) from Windows.

Read the documentation ...

http://msdn.microsof...418(VS.85).aspx

#17 Goz

    Senior Member

  • Members
  • PipPipPipPip
  • 575 posts

Posted 05 May 2009 - 09:58 AM

because i'm feeling nice (Even though the link above has a perfect explanation of how to use FindFirstFile) ... this code should work. If it doesn't i suggest you try to figure out why (because I haven't compiled or run the code, myself) using the documentation.


HANDLE hHandle;

WIN32_FIND_DATA data;

std::vector<TCHAR*> Directories;


hHandle = FindFirstFile("Media/LightProbes/*", &data );


BOOL bMoreFiles = TRUE;

while(bMoreFiles == TRUE)

{

	const size_t strLen	= _tcslen( data.cFileName ) + 1;

	TCHAR* pNewStr		= new TCHAR[strLen];

	_tcscpy_s( pNewStr, strLen, data.cFileName );

	Directories.push_back( pNewStr );


	bMoreFiles = FindNextFile( hHandle, &data );

}


#18 rouncer

    Senior Member

  • Members
  • PipPipPipPip
  • 2722 posts

Posted 05 May 2009 - 10:02 AM

Why dont you learn the windows file explorer.

#19 Goz

    Senior Member

  • Members
  • PipPipPipPip
  • 575 posts

Posted 05 May 2009 - 10:06 AM

rouncer said:

Why dont you learn the windows file explorer.

How does that help you to programmatically enumerate files in a directory?

#20 Phlex

    Member

  • Members
  • PipPip
  • 53 posts

Posted 05 May 2009 - 10:22 AM

Cool, it seems to work prefectly now, here's the code for getting all of a certain type of file ina folder (I find all .dds files obviously, just change the file extension on the FindFirstFile function);


	HANDLE hHandle;
	WIN32_FIND_DATA pData;
	std::vector<TCHAR*> Directories;

	hHandle = FindFirstFile("Media/LightProbes/*.dds", &pData);

	const size_t strLen	= _tcslen( pData.cFileName ) + 1;
	TCHAR* pNewStr		= new TCHAR[strLen];
	_tcscpy_s( pNewStr, strLen, pData.cFileName );
	Directories.push_back( pNewStr );

	BOOL bMoreFiles = TRUE;
	while(bMoreFiles == TRUE)
	{
		bMoreFiles = FindNextFile(hHandle, &pData);
		if(bMoreFiles == TRUE)
		{
			const size_t strLen	= _tcslen( pData.cFileName ) + 1;
			TCHAR* pNewStr		= new TCHAR[strLen];
			_tcscpy_s( pNewStr, strLen, pData.cFileName );
			Directories.push_back( pNewStr );
		}
	}

As a note to others, make sure you save the name of whatever cFileName is after FindFirstFile is called otherwise you will miss it out as FindNextFile will not go back to the start of the file, thanks heaps Goz for your help, just another couple of questions if you don't mind?

1. ok, so I've got the name and file extension, how can I effectively go


LPCSTR caPaths[Directories.size()];

for(int i = 0; i < Directories.size(); i++)
{
caPaths[i] = LPCSTR("Media/LightProbes/" + Directory[i]);
}


??


2. What exactly is an "access violation"? I've seen them so many times but never actually known what they are.

Again thank you for your help.





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users