Wednesday, December 15, 2021

Getting file/folder list in Windows and Linux

Getting file/folder list in Windows and Linux without using libraries is a tricky business. In Windows Visual Studio, there is also a character set setting (Project properties - Advanced - Character Set) which has to be taken into account.

#ifdef _WIN32
#include <windows.h> //NOTE: The first include must be windows.h
#include <stdio.h>
#include <tchar.h>
#include <strsafe.h>
#include<comdef.h> //to convert WCHAR to char*
#pragma comment(lib, "User32.lib")
namespace FileUtils { //NOTE: namespace must come after #include statements, otherwise you will get strange errors.
//https://docs.microsoft.com/en-us/windows/win32/fileio/listing-the-files-in-a-directory
int GetAll(DWORD fileAttribute, const char* folderName, char fileNames[][MAX_FILE_NAME_LENGTH]) {
WIN32_FIND_DATA ffd;
HANDLE hFind = INVALID_HANDLE_VALUE;
DWORD dwError = 0;
TCHAR szDir[MAX_FOLDER_NAME_LENGTH];
#ifdef UNICODE //Project properties - Advanced - Character Set
//convert const char* to LPCWSTR:
int size = MultiByteToWideChar(CP_ACP, 0, folderName, -1, NULL, 0);
TCHAR folderNameLPCWSTR[MAX_FOLDER_NAME_LENGTH];
MultiByteToWideChar(CP_ACP, 0, folderName, -1, (WCHAR*)folderNameLPCWSTR, size);
// Prepare string for use with FindFile functions. First, copy the string to a buffer, then append '\*' to the directory name.
StringCchCopy(szDir, MAX_FOLDER_NAME_LENGTH, (STRSAFE_LPCWSTR)folderNameLPCWSTR);
StringCchCat(szDir, MAX_FOLDER_NAME_LENGTH, TEXT("\\*"));
#else //Multi-Byte
sprintf(szDir, "%s\\*", folderName);
#endif
// Find the first file in the directory:
//hFind = FindFirstFile(szDirLPCWSTR, &ffd);
hFind = FindFirstFile(szDir, &ffd);
if (INVALID_HANDLE_VALUE == hFind) {
printf("Error: Folder (%s) does not exist!\n", folderName);
return 0;
}
// List all the files in the directory with some info about them.
size_t nFiles = 0;
do {
if (ffd.dwFileAttributes & fileAttribute) {
//convert wchar to char*:
_bstr_t b(ffd.cFileName);
const char* fileName = b;
strcpy(fileNames[nFiles], fileName);
//filesize.LowPart = ffd.nFileSizeLow;
//filesize.HighPart = ffd.nFileSizeHigh;
//_tprintf(TEXT(" %s %ld bytes\n"), ffd.cFileName, filesize.QuadPart);
nFiles++;
if (nFiles > MAX_NB_OF_FILES) {
printf("Error: nFiles (%d) > MAX_NB_OF_FILES (%d)!\n", nFiles, MAX_NB_OF_FILES);
return 0;
}
}
} while (FindNextFile(hFind, &ffd) != 0);
dwError = GetLastError();
if (dwError != ERROR_NO_MORE_FILES) {
printf("Error: %d\n", dwError);
return 0;
}
FindClose(hFind);
//return dwError;
return nFiles;
}
int GetAllFolders(const char* folderName, char fileNames[][MAX_FILE_NAME_LENGTH]) {
return GetAll(FILE_ATTRIBUTE_DIRECTORY, folderName, fileNames);
}
#define FILE_ATTRIBUTE_FILE (8224)
int GetAllFiles(const char* folderName, char fileNames[][MAX_FILE_NAME_LENGTH]) {
return GetAll(FILE_ATTRIBUTE_FILE, folderName, fileNames);
}
#else //POSIX, Linux
//https://stackoverflow.com/a/4204758/51358
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#define FILE_ATTRIBUTE_DIRECTORY (4)
#define FILE_ATTRIBUTE_FILE (8)
namespace FileUtils {
int GetAll(const char* folderName, unsigned char d_type, char fileNames[][MAX_FILE_NAME_LENGTH]) {
DIR* d = opendir(folderName);
int nFiles = 0;
if (d) {
struct dirent* dir;
while ((dir = readdir(d)) != NULL) {
if(d_type == dir->d_type) {
//printf("name: %s, type: %d\n", dir->d_name, dir->d_type);
strcpy(fileNames[nFiles], dir->d_name);
nFiles++;
}
}
closedir(d);
}
return nFiles;
}
int GetAllFolders(const char* folderName, char fileNames[][MAX_FILE_NAME_LENGTH]) {
return GetAll(folderName, FILE_ATTRIBUTE_DIRECTORY, fileNames);
}
int GetAllFiles(const char* folderName, char fileNames[][MAX_FILE_NAME_LENGTH]) {
return GetAll(folderName, FILE_ATTRIBUTE_FILE, fileNames);
}
#endif // _WIN32
}

No comments:

Post a Comment