472,101 Members | 1,461 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,101 software developers and data experts.

List files in directory

Hello, I've been trying to get a list of files from given directory in C++ (with win32)
but i encountered some weird problems

Expand|Select|Wrap|Line Numbers
  1. //test snippet
  2. #include <windows.h>
  3. #include <stdio.h>
  4. #include <iostream>
  6. int main()
  7. {
  9. //find file data    
  10.     WIN32_FIND_DATA findFileData;
  11.  HANDLE hFind = FindFirstFile((LPCSTR)"C:\\Documents and                    
  12. Settings\\Me\\Desktop\\Pictures", &findFileData);
  15. //print it out
  16.         std::cout <<"Files in dir:" <<std::endl;
  17.     std::cout <<(char*)&findFileData.cFileName<<std::endl; //problem might be here
  20.     char pause;
  21.     std::cin>> pause;
  22.     return 0;
  23. }
my output is:
Expand|Select|Wrap|Line Numbers
  1. Files in dir
  2.       Pictures
and I'm certain that it's a folder, not a file...

even when I do
Expand|Select|Wrap|Line Numbers
  1.  FindNextFile (hFind, &findFileData)
I'm still getting "Pictures"!
anything wrong with the code?
why am i not getting an actual file name?
wondering if it's my WCHAR to char* cast...(ugly isnt it?)

is there a quick way to find the number of files in a directory?
(I am using VC++ 2008 with Windows XP Pro)

Thank you in advance,
May 11 '09 #1
20 47096
9,208 Expert Mod 8TB
I believe a folder is a type of file.

I assume you have read this: http://msdn.microsoft.com/en-us/libr...18(VS.85).aspx
May 11 '09 #2
So, i got that all good and figured out :p

Expand|Select|Wrap|Line Numbers
  1. //this goes to superduperwhat.cpp
  2. #include <windows.h>
  3. #include <stdio.h>
  4. #include <iostream> 
  5. char* locjpg = "C:\\Documents and Settings\\yair\\Desktop\\UNIMPICS\\*.jpg";
  6. char* locbmp = "C:\\Documents and Settings\\yair\\Desktop\\UNIMPICS\\*.bmp"; 
  7. char* arr[50];
  8. char* nfilen;
  11. int main()
  12. {
  13.     char desOfile[80]; //destination of file, load to a LPDIRECT3DTEXTURE9
  14.     WIN32_FIND_DATA findFileData;
  15.     HANDLE hFind = FindFirstFile((LPCSTR)locjpg, &findFileData);
  16.     std::cout <<"Picture files in dir:" <<"\n"<<locjpg<<"\n"<<locbmp<<"\n\n"<<std::endl;
  17.     std::cout <<findFileData.cFileName<<"\n"<<std::endl;
  18.     nfilen = findFileData.cFileName;
  19.     strcpy(desOfile,"C:\\Documents and Settings\\yair\\Desktop\\UNIMPICS\\");
  20.     strcat(desOfile,nfilen);
  23. //change to something to navigate between images, add bmp for search 
  24.     for (unsigned f=0;f<20;f++) //change 
  25.     {
  26.         //tomalloc    
  27.         FindNextFile(hFind,&findFileData);
  28.         arr[f] = findFileData.cFileName;
  29.         strcpy(desOfile,"C:\\Documents and Settings\\yair\\Desktop   \\UNIMPICS\\");
  30.         strcat(desOfile,nfilen);
  31.         std::cout <<arr[f]<<std::endl;
  32.         std::cout<<desOfile<<"\n\n"<<std::endl;
  33.           /*arr[f]=desOfile;  for actual app IMPORTANT*/
  36.     } 
  42.     char pause;
  43.     std::cin>> pause;
  44.     return 0;
  45. }
O.K. so everything is nice and happy until the for loop, how do i know how many files are in the directory so i can know how many times to loop? and maybe how many chars i need for "arr".

Was that a squirrl?
May 12 '09 #3
9,208 Expert Mod 8TB
You stay in the loop until FindNextFile returns FALSE. The call GetLastError and look for ERROR_NO_MORE_FILES.

If you counted the number of times FindNextFile returned TRUE, then you have the number of files.

Be sure to read the MSDN page for FindNextFile.
May 12 '09 #4
Umm.... it just returns the last file it finds(the same file again and again) until i tell it to stop!

Edit: HAHA no need to actually check for the error but thx for pointing my attention at the fact that it returns something if it fails... forgot about that(yep, stupidity gets over me sometimes, well really often)

Expand|Select|Wrap|Line Numbers
  1. while(FindNextFile(hFind,&findFileData))
  2.     {
  4.         f++;
  5.         arr[f] = findFileData.cFileName;
  6.         strcpy(desOfile,"C:\\Documents and Settings\\yair\\Desktop\\UNIMPICS\\");
  7.         strcat(desOfile,nfilen);
  8.         std::cout <<arr[f]<<std::endl;
  9.         std::cout<<desOfile<<"\n\n"<<std::endl;
  12.     }
this looks much more neat then the last one and works well.

not paying attention to details gets me into panic

for the Left4Dead players:
"director_panic_forever 1;director_force_panic_event 1;z_spawn witch;z_spawn tank"
bind that with the quotes to any key and watch ur friends run away in fear...
May 12 '09 #5
9,065 Expert Mod 8TB
I don't know what you think this
Expand|Select|Wrap|Line Numbers
  1.     arr[f] = findFileData.cFileName;
does but probably not what you think. arr ends up as an array of pointers all pointing to the same buffer so all point to the same data, the last file you found.
May 12 '09 #6
so what do i need to do in order to save this the right way?
its not directed to the last file i found its directed to nothing, say i have exceeded the length of the streamsize when i try to print out arr[element]
my right- to actually store the letters inside the (char*) in the spacific element of the array! (it is a char* array)
cant find a str method for this >,< or is there?
May 13 '09 #7
so what do i need to do to findFileData?
May 13 '09 #8
well think i made my work difficult cos arr is an array of pointers >,<
how else can i store whole strings in a non-pointer way?
May 13 '09 #9
This situation just calls for it.
If you use Unicode compiler settings replace string with wstring.

Expand|Select|Wrap|Line Numbers
  1. #include <vector>
  2. #include <string>
  4. using namespace std;
  7. vector<string> vfList;
  8. vfList.push_back("file1.txt");
  9. vfList.push_back("file2.txt");
  10. // keep pushing file names as long as you want
  12. vector<string>::iterator itr;
  13. for(itr = vfList.begin(); itr != vfList.end(); itr++)
  14. {
  15.     // Do actions with each file.
  16.     // Use itr->c_str() to get the string buffer
  17.     // or *itr to get the actual C++ string object.
  18. }

Now, I'm not really sure why you use the raw Windows API, but I'd suggest scraping this whole thing and using Boost.Filesystem instead.
The Win32 API was designed for C programmers some 15+ years ago. Even Microsoft doesn't want it anymore (see .NET).
May 13 '09 #10
using multi-byte charset, :p this vector thing is new to me gonna read on that some
vector doesnt seem to have this method.
do i need to a include a .lib or do anything special before using vectors?

some time later in the day>>
Darnit! its a '::' method (I'm tired...) was just playing around and found it.

If the world is crashing down on you,
check for missing semicolons.
May 13 '09 #11
Damn i didnt notice u using the namespace...
I was so frustrated why it won't work when i just do "vector<string>"...

or do i need to
the while loop goes through files in the directory
the "findFileData.cFileName" is a CHAR(WCHAR in unicode)
do i just use push back in the while loop?
does that create a new element or creates and stuffs a new element?

Expand|Select|Wrap|Line Numbers
  1. int main()
  2. {
  4.     char desOfile[80];
  5.     std::vector<string> victor;
  6.     std::vector<string>::iterator itr;
  8.     WIN32_FIND_DATA findFileData;
  9.     HANDLE hFind = FindFirstFile((LPCSTR)locjpg, &findFileData);
  10.     std::cout <<"Picture files in dir:" <<"\n"<<locjpg<<"\n"<<locbmp<<"\n\n"<<std::endl;
  11.     std::cout <<findFileData.cFileName<<"\n"<<std::endl;
  12.     nfilen = findFileData.cFileName;
  13.     strcpy(desOfile,"C:\\UNIMPICS\\");
  14.     strcat(desOfile,nfilen);
  18.     for(itr = victor.begin();itr!=victor.end();itr++)
  19.     {
  20.         victor.push_back(findFileData.cFileName);
  21.         strcpy(desOfile,"C:\\UNIMPICS\\");
  22.         strcat(desOfile,"\\");
  23.         strcat(desOfile,nfilen);
  24.         std::cout<<desOfile<<"\n\n"<<std::endl;
  28.     }
say i have that, what does <string> should be?

"oh i forgot u used the std..."
Using STD in your source code just doesn't sound right anymore...
May 13 '09 #12
Damn me... forgot u used the namespace again... (string)

after a nightmare of trial and error and reading MSDN...
i got it... i finally got it :D
got it all figured out and i probably should stop writing everything I'm panicing with... (see silly posts above)

Thank you so much.
I'm not gonna use arrays again!!! (wait what? just kidding)
the iterator doesnt appear to have any method called c_str though.

for the sake of knowledge, here is the complete, functional while loop
Expand|Select|Wrap|Line Numbers
  1.     while(FindNextFile(hFind,&findFileData))
  2.     {
  3.         int temp;    
  4.         victor.push_back(findFileData.cFileName);
  5.         strcpy(desOfile,"C:\\UNIMPICS\\");
  6.         strcat(desOfile,nfilen);
  7.         cout<<desOfile<<"\n\n"<<endl;
  8.         cout<<victor[f]<<endl;
  9.         f++;
  10.     }
  11. }

Everybody's got a brain,
learn how to hack it, and the world is yours!
May 14 '09 #13
What is this **** ?!!!!
Under Windows, you must use Win32 api. Period.
All OS from Win 95 to Windows 7 are written in C, C++, ASM Win32, with the Win32 api
All Windows softwares are written with Win32 api (MFC is a wrapper)
All Windows games are written with Win32 api (DirectX and OpenGL)
Incredible to read such things...
May 15 '09 #14
9,065 Expert Mod 8TB
This is partly a matter of semantics, if a wrapper you use then uses the WIN32 API you are still not using it and do (should) not really need to know anything about it only about the interface the wrapper you are using defines.

Using WIN32 directly is definitely not what Microsoft want you to do nor for that matter do they want you using MFC. Both of these are out-dated forums of writing programs for Windows, although I imagine they are both still used.

The prefered method for creating Windows application is now .NET. It would not be unreasonable to assume that the Windows implementation of the .NET Framework makes some use of the WIN32 interface when implemented on the Windows platform, however Windows is not the only platform that the .NET framework has been implemented on so using .NET is not implicitly using WIN32.

In a complex system like Windows you use the interface of your choice and you do not worry too much about what interfaces that interface uses.

So you blanket statement that all Windows development uses the WIN32 API make be technically correct if you delve down through the layers of code deeply enough but it is not the environment that most Windows application programmers use and for straight programming it is certainly not in very common usage any more.

Your view is out-dated and presented in a belligerent manner and not that useful.
May 15 '09 #15
Is there a way to solve my problem without using a template (for educational purpose)?
The rawer the better(no assembly code lol),
Even only general guidelines on how to solve this.
May 18 '09 #16
9,065 Expert Mod 8TB
By without a template do you mean without using vector and string?
May 18 '09 #17
Without using STL or any other templates.
May 18 '09 #18
9,065 Expert Mod 8TB
I can think of 2 ways either use a dynamically allocated array of pointers.

That is you allocate and array of pointers to char (say 10 to start off with). Each time you read a file name you allocate memory to hold that file name and assign it to the next pointer in the array. When you reach the 11th file then you reallocate you array of 10 pointers to be 16 pointers (I believe 1.6 is an efficient growth factor). You will also have to keep a count of how many file-names you have read and make sure you deallocate the memory correctly.

You will need to use the function malloc, realloc and free for memory handling.

The second option is a linked list (look it up on wikipedia). I linked list can just be grown as you read more file names, you just need adding nodes to the list. Again you will need to use malloc and free (but not realloc).
May 18 '09 #19
Think a linked list is the way to go on this one.
(In these situation python is so tempting)

http://www.csref.info <-> code reference site.
May 19 '09 #20
Used an allocated array but with new(C++) instead of malloc(C)

Tried malloc too, found that new is simply faster (though delete is slower than free, and there's no reallocation with new :p)

Expand|Select|Wrap|Line Numbers
  2. char** pt;
  3. pt = new char*[50];
  4. unsigned n=0;
  5. for(/*noimportant*/;n++)
  6. {
  7. /*lala
  8. lala*/
  9. pt[n]= hFindFile.cFileName;
  10. }
  11. for (n=0;pt[n]!=NULL;n++)
  12. {
  13.     cout <<pt[n]<<', ';
  14. }
  15. delete [] pt;
  16. return 0;
  17. }
May 23 '09 #21

Post your reply

Sign in to post your reply or Sign up for a free account.

Similar topics

3 posts views Thread by Hamed | last post: by
1 post views Thread by Shawn Mehaffie | last post: by
7 posts views Thread by Kristan | last post: by
reply views Thread by leo001 | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.