Solved

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

Posted on 2011-02-25
31
418 Views
Last Modified: 2012-05-11
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.
0
Comment
Question by:pgmerLA
  • 9
  • 8
  • 4
  • +4
31 Comments
 
LVL 74

Expert Comment

by:käµfm³d 👽
ID: 34980910
For which environment?
0
 

Author Comment

by:pgmerLA
ID: 34981063
MS VS 2008
0
 
LVL 86

Accepted Solution

by:
jkr earned 500 total points
ID: 34981361
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
 
LVL 32

Expert Comment

by:sarabande
ID: 34981941
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
 

Author Comment

by:pgmerLA
ID: 34982494
Could you give me a simple sample using findnextfile() in MS VS 2008
0
 
LVL 32

Expert Comment

by:phoffric
ID: 34982808
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
 
LVL 86

Expert Comment

by:jkr
ID: 34984414
>>Could you give me a simple sample using findnextfile() in MS VS 2008

That is what I posted above...
0
 
LVL 86

Expert Comment

by:jkr
ID: 34984455
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
 
LVL 2

Expert Comment

by:basavaraj_kn
ID: 34986787
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
 
LVL 32

Expert Comment

by:sarabande
ID: 34991465
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
 
LVL 32

Expert Comment

by:sarabande
ID: 34991471
In call of FindFirstFile remove the closing ) after the search path.

Sara
0
 

Author Comment

by:pgmerLA
ID: 34992507
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
Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

 
LVL 86

Expert Comment

by:jkr
ID: 34992531
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
 
LVL 32

Expert Comment

by:sarabande
ID: 34995270
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
 
LVL 32

Expert Comment

by:sarabande
ID: 34995690
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
 
LVL 32

Expert Comment

by:sarabande
ID: 34995714
pgamerLA, please ask for the code lines you don't understand so that all who were particpating can answer your questions.

Sara
0
 

Author Comment

by:pgmerLA
ID: 35063130
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
 
LVL 11

Expert Comment

by:DeepuAbrahamK
ID: 35065897
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
 
LVL 32

Expert Comment

by:sarabande
ID: 35067271
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
 

Author Comment

by:pgmerLA
ID: 35079358
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
 
LVL 32

Expert Comment

by:sarabande
ID: 35081326
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
 

Author Comment

by:pgmerLA
ID: 35091994
thanks a lot.
0
 

Author Comment

by:pgmerLA
ID: 35110350
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
 

Author Comment

by:pgmerLA
ID: 35122615
Hi Vee Mod,
I think it's a great idea. Let's do it.
0
 

Author Comment

by:pgmerLA
ID: 35122994
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

Featured Post

Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Unlike C#, C++ doesn't have native support for sealing classes (so they cannot be sub-classed). At the cost of a virtual base class pointer it is possible to implement a pseudo sealing mechanism The trick is to virtually inherit from a base class…
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.

707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now