how do you list all the txt files from a folder using c++

Hi, what function and header do you have to use to list all the txt files from a folder.

could you also give a very simple SAMPLE code?

Thanks a lot.
pgmerLAAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

käµfm³d 👽Commented:
For which environment?
0
pgmerLAAuthor Commented:
MS VS 2008
0
jkrCommented:
Take a look at http://msdn.microsoft.com/en-us/library/aa365200%28VS.85%29.aspx ("Listing the Files in a Directory") - modified for a *.txt extension, that would be
#include <windows.h>
#include <tchar.h> 
#include <stdio.h>
#include <strsafe.h>
#pragma comment(lib, "User32.lib")

void DisplayErrorBox(LPTSTR lpszFunction);

int _tmain(int argc, TCHAR *argv[])
{
   WIN32_FIND_DATA ffd;
   LARGE_INTEGER filesize;
   TCHAR szDir[MAX_PATH];
   size_t length_of_arg;
   HANDLE hFind = INVALID_HANDLE_VALUE;
   DWORD dwError=0;
   
   // If the directory is not specified as a command-line argument,
   // print usage.

   if(argc != 2)
   {
      _tprintf(TEXT("\nUsage: %s <directory name>\n"), argv[0]);
      return (-1);
   }

   // Check that the input path plus 3 is not longer than MAX_PATH.
   // Three characters are for the "\*" plus NULL appended below.

   StringCchLength(argv[1], MAX_PATH, &length_of_arg);

   if (length_of_arg > (MAX_PATH - 3))
   {
      _tprintf(TEXT("\nDirectory path is too long.\n"));
      return (-1);
   }

   _tprintf(TEXT("\nTarget directory is %s\n\n"), argv[1]);

   // Prepare string for use with FindFile functions.  First, copy the
   // string to a buffer, then append '\*' to the directory name.

   StringCchCopy(szDir, MAX_PATH, argv[1]);
   StringCchCat(szDir, MAX_PATH, TEXT("\\*.txt")); // <---------- only look for *.txt!

   // Find the first file in the directory.

   hFind = FindFirstFile(szDir, &ffd);

   if (INVALID_HANDLE_VALUE == hFind) 
   {
      DisplayErrorBox(TEXT("FindFirstFile"));
      return dwError;
   } 
   
   // List all the files in the directory with some info about them.

   do
   {
      if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
      {
         _tprintf(TEXT("  %s   <DIR>\n"), ffd.cFileName);
      }
      else
      {
         filesize.LowPart = ffd.nFileSizeLow;
         filesize.HighPart = ffd.nFileSizeHigh;
         _tprintf(TEXT("  %s   %ld bytes\n"), ffd.cFileName, filesize.QuadPart);
      }
   }
   while (FindNextFile(hFind, &ffd) != 0);
 
   dwError = GetLastError();
   if (dwError != ERROR_NO_MORE_FILES) 
   {
      DisplayErrorBox(TEXT("FindFirstFile"));
   }

   FindClose(hFind);
   return dwError;
}


void DisplayErrorBox(LPTSTR lpszFunction) 
{ 
    // Retrieve the system error message for the last-error code

    LPVOID lpMsgBuf;
    LPVOID lpDisplayBuf;
    DWORD dw = GetLastError(); 

    FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER | 
        FORMAT_MESSAGE_FROM_SYSTEM |
        FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL,
        dw,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        (LPTSTR) &lpMsgBuf,
        0, NULL );

    // Display the error message and clean up

    lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, 
        (lstrlen((LPCTSTR)lpMsgBuf)+lstrlen((LPCTSTR)lpszFunction)+40)*sizeof(TCHAR)); 
    StringCchPrintf((LPTSTR)lpDisplayBuf, 
        LocalSize(lpDisplayBuf) / sizeof(TCHAR),
        TEXT("%s failed with error %d: %s"), 
        lpszFunction, dw, lpMsgBuf); 
    MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK); 

    LocalFree(lpMsgBuf);
    LocalFree(lpDisplayBuf);
}

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Cloud Class® Course: CompTIA Healthcare IT Tech

This course will help prep you to earn the CompTIA Healthcare IT Technician certification showing that you have the knowledge and skills needed to succeed in installing, managing, and troubleshooting IT systems in medical and clinical settings.

sarabandeCommented:
a portable solution you can get by downloading dirent.h for windows.

you also can make quick and dirty

   system("dir /b c:\\temp\\*.txt > temp_txtfiles.log");

and then read the temp_txtfiles.log.

note, system call is not recommendable for gui application cause a console window would pop-up.

Sara

0
pgmerLAAuthor Commented:
Could you give me a simple sample using findnextfile() in MS VS 2008
0
phoffricCommented:
Take a look at http://www.experts-exchange.com/Programming/Languages/C/Q_26654614.html
Here are some excerpts (please review the above question for more details):

Use dirent.h functions, opendir(), readdir(), and closedir()

Portable code Reference (not just for Unix): http://www.ibm.com/developerworks/aix/library/au-unix-readdir.html

If you want to keep your program portable, you can use ftell and fseek to determine the filesize (in bytes). You would have to fopen the filename using binary.
    http://www.cplusplus.com/reference/clibrary/cstdio/fseek/
    http://www.cplusplus.com/reference/clibrary/cstdio/ftell/
    http://www.cplusplus.com/reference/clibrary/cstdio/fopen/

But, if want the permissions, group, owner, and date as well, then you will have to use non-standard C functions.


dir = opendir( "some/path/name" )  
entry = readdir( dir )  
while entry is not NULL:  
    do_something_with( entry )  
    entry = readdir( dir )  
closedir( dir )

Open in new window

0
jkrCommented:
>>Could you give me a simple sample using findnextfile() in MS VS 2008

That is what I posted above...
0
jkrCommented:
Or, in an nutshell:
#include <windows.h>

void main () {

	WIN32_FIND_DATA fd;

	HANDLE hFind = FindFirstFile(_T("c:\\path\\*.txt"),&fd);

	while (hFind) {

		wprintf(_T("File: %s\n""),fd.cFileName);

		if (!FindNextFile(hFind,&fd)) break;
	}
}

Open in new window

0
basavaraj_knCommented:
Hi

You can use below, this pushes the file name with path to a vector, which you can use for your purpose.

You need to include headers #include <sys/types.h> and #include <dirent.h> to read the directory, you can use #include <errno.h> to know about any error in opening of file

try the below code, it should work for you

#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
#include <vector>
#include <string>
#include <iostream>


int listDirectoryFiles (std::string strDirName, std::vector<string> &dirFiles, bool listNestedDir=false, std::string fileNamePrefix="/")
{
	DIR *ptrDir;
	ptrDir = opendir(strDirName.c_str())

	if(ptrDir == NULL)
	{
		std::cout << "Last error: " << errno << ", in opening directory " << strDirName << std::endl;
		return errno;
	}


	struct dirent *ptrDirEntry;
	while ((ptrDirEntry = readdir(ptrDir)) != NULL)
	{
		if ( ptrDirEntry->d_type == DT_REG) //If this is a file
		{
			std::string fileName = fileNamePrefix;
			fileName += ptrDirEntry->d_name;
			dirFiles.push_back(fileName);
		}
		else if (ptrDirEntry->d_type == DT_DIR) //Directory
		{
			if ( listNestedDir )
				listDirectoryFiles ( ptrDirEntry->d_name, dirFiles, listNestedDir, ptrDirEntry->d_name );
		}

	}

	closedir(ptrDir);

	return true;
}

Open in new window


Thanks
Basavaraj
0
sarabandeCommented:
assuming you would like c++ sample code for ANSI text files only, the 'nutshell' code of jkr would turn to the code below.

you would need to create a win32 console project with the MultiByte Characterset  (and not UNICODE).

Sara
#include <iostream>
#include <windows.h>

int main () 
{
   WIN32_FIND_DATA fd;

   HANDLE hFind = FindFirstFile("c:\\path\\*.txt"),&fd);
   if (hFind == INVALID_HANDLE_VALUE)
      return GetLastError();

   do 
   {
      std::cout << "File: " << fd.cFileName << std::endl;
   } 
   while (FindNextFile(hFind, &fd) != NULL);
   if (GetLastError() != ERROR_NO_MORE_FILES)
      return GetLastError();
   FindClose(hFind);
   return 0;
}

Open in new window

0
sarabandeCommented:
In call of FindFirstFile remove the closing ) after the search path.

Sara
0
pgmerLAAuthor Commented:
Hi Sara,
Thanks for the code.
could you please add documentation for the code.
I don't understand a lot of the lines.
Thanks a lot.
0
jkrCommented:
pgamerLA, sarabande knows prefectly well that posting slightly altered code is not welcomed at EE. May I ask you on the other side why you are ignoring what was posted before?
0
sarabandeCommented:
jkr, sorry for having angered you.

i did change the code cause it was pure c and and not c++ even when it would compile with a c++ compiler. it also uses proprietary T-switch of microsoft which in my opinion is not a part of a proper solution. i also added correct handling of the return codes.

i also made a reference to your code and did not pretend it was mine. sorry, if it wasn't correct nevertheless. i am still a beginner here in ee.

Sara



0
sarabandeCommented:
the

   while (hFind)

in the code of jkr would lead into an endless loop in case the handle is invalid, what is the case if the initial call to FindFirstFile failed. the return value then is -1 (== INVALID_HANDLE_VALUE) what would be 'true' when used in while condition.

if you look to all changes i made to the code of jkr it is more than slightly changed.

Sara
0
sarabandeCommented:
pgamerLA, please ask for the code lines you don't understand so that all who were particpating can answer your questions.

Sara
0
pgmerLAAuthor Commented:
Hi SaraBande,

I am having issues with the code. I get a compiling error. I am using MS VS 2008.

Could you please tell me where I made a mistake?

Thanks.
#include <iostream>
#include<windows.h>

int main()
{ WIN32_FIND_DATA fd;
HANDLE hFind = FindFirstFile(("c:\\Documents and Settings\\Massoud\\My Documents\\Visual Studio 2008\\*.txt"),&fd);
if (hFind ==INVALID_HANDLE_VALUE) return GetLastError();
do
{std::cout<<"File: "<<fd.cFileName<<std::endl;
}while(FindNextFile(hFind, &fd) != NULL);
if (GetLastError() != ERROR_NO_MORE_FILES) return GetLastError();
FindClose(hFind);
return 0;
}

Open in new window

0
Deepu AbrahamR & D Engineering ManagerCommented:
What  you have posted above just works fine. What is the compilation error? If you can put all the details while posting will help you get quick answers from the Experts here.
0
sarabandeCommented:
I compiled with VS2008 and had no problems.

you should have a win32 console project with multi-byte characterset and precompiled headers off.

the settings can be made in project - properties (you find the character set in 'Configuration Properties - General and precompiled headers in Configuration Properties - C++ - Precompiled Headers).

Sara
0
pgmerLAAuthor Commented:
WOW.
It works!

can you tell what's the difference between using win32 console project and win32 project?(why use one and not the other)

and why we used multi-byte character set as opposed to the default version?

Thanks a lot Sara.
0
sarabandeCommented:
win32 console project expects main (or _tmain) as start function while win32 project expect WinMain function. the latter is supposed to already have initialisations for Windows what means a graphical user interface. if you don't have a WinMain function in a Win32 project normally the linker complains because of the missing start function.

the initial character set for Visual Studio projects can be UNICODE (more precisely UTF.16 what is 16-bit layer 0 of UNICODE) or Multi-Byte. the latter normally is named ANSI and is equivalent in codes 0 ... 255 (== 2^8 codes) to UTF-16 which has a maximum of 65536 (2^16) codes. though called multibyte it actually is a single-byte (8-bit) character set while UTF-16 is a double-byte character set.

those settings are relevant when using WINAPI functions which have character arrays or character pointers as arguments. then these types were defined as TCHAR arrays or LPTSTR pointers (and more). those types will map to char, char *, ... in case of multibyte character set and map to wchar_t, wchar_t * when UNICODE is set. So, you can get compiler errors if you pass a char* to GetCurrentDirectory and UNICODE is switched on cause GetCurrentDirectory expects a buffer of wide characters wchar_t. they also can lead to errors if you have a _tmain function rather than main cause the LPTSTR [] array argument would map to wchar_t * [] and not to char * [].

Sara
0
pgmerLAAuthor Commented:
thanks a lot.
0
pgmerLAAuthor Commented:
I somewhat agree with you.
However, I asked for a "very SIMPLE" code in my original question. I am only in my second class in C++ programming.
I felt that Sarabande answered my question by providing a simple code.
I have not doubt that jkr's code is great, but the code seems really hard(at this point).
I am new to EE. What do you suggest I do?
0
pgmerLAAuthor Commented:
Hi Vee Mod,
I think it's a great idea. Let's do it.
0
pgmerLAAuthor Commented:
Hi SaraBande,

could you post your answer on this page so that I can reward you for your code?

http://www.experts-exchange.com/Programming/Languages/CPP/Q_26883661.html
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C++

From novice to tech pro — start learning today.