File Attributes and Directory Processing

We can search a directory with the functions FindFirstFile(), FindNextFile(), and FindClose().

The FindFirstFile() function accepts two parameters, a string pointer indicating the file name, and a pointer to a WIN32_FIND_DATA structure. We use the FindFirstFile() function to obtain a search handle, which is the return value of the function.

The WIN32_FIND_DATA structure has 9 fields. The first field, dwFileAttributes, is a DWORD value indicating the file attributes via bit settings. The next three fields are FILETIME structures that indicate the creation time, last access time, and last write time of the file. The next two values are DWORD values that indicate the high order and low order value of the file size, in bytes.  The value of the high-order DWORD value is 0, unless the size of the file is greater than MAXDWORD. 

#include "stdafx.h"
#include <Windows.h>

int main()
{
 WIN32_FIND_DATA structFindData;

 //find the cpp file in this folder
 TCHAR tszFilename[] = _T("*.cpp");
 HANDLE hFile;
 hFile = FindFirstFile(tszFilename, &structFindData);

 //our source code is certainly less than this number
 printf("The size of MAXDWORD is %lu\n", MAXDWORD);

 if (hFile == INVALID_HANDLE_VALUE) {
 printf("Error finding file.\n");
 }

 if (structFindData.nFileSizeHigh == 0) {
 _tprintf(_T("The size of %s is %d bytes\n"), structFindData.cFileName, structFindData.nFileSizeLow);
 }

 return 0;
}

Note that the cFileName field is not the pathname; it is just the file name by itself.

In order to find multiple files matching the search criteria, we can call the FindNextFile() function, passing in the search handle we obtained from the FindFirstHandle() function.

The FindNextFile() function returns a Boolean value, true if the function found another file, false if the file did not find another file or received bad arguments. We can use GetLastError() to check if the functions failed to find another matching file.

#include "stdafx.h"
#include <Windows.h>

int main()
{
 WIN32_FIND_DATA structWin32;
 //find all files/directories in C drive
 HANDLE hSearch = FindFirstFile(_T("C:\\*"), &structWin32);

 _tprintf(_T("%s\n"), structWin32.cFileName);

 //FindNextFile returns a Boolean
 while (FindNextFile(hSearch, &structWin32)) {
 _tprintf(_T("%s\n"), structWin32.cFileName);
 }
 if (GetLastError() == ERROR_NO_MORE_FILES) {
 printf("No more files...\n");
 }

 //FindClose to close search handle
 FindClose(hSearch);

 return 0;
}

Be sure and use the FindClose() function to close the search handle, not CloseHandle().

We can obtain a file’s full pathname using the GetFullPathName() function. The GetFullPathName() function has four parameters. The first parameter is the name of the file. The second parameter is the buffer size in TCHARs of the buffer that is to get the null-terminated string for the drive and path. The third argument is a pointer to the buffer that receives the null-terminated string for the drive and path. The fourth parameter is optional.

 #include "stdafx.h"
#include <Windows.h>

int main()
{
 
 WIN32_FIND_DATA structFData;
 HANDLE hFindFile;
 TCHAR tszBuffer[MAX_PATH];
 hFindFile = FindFirstFile(_T("."), &structFData);

 if (hFindFile == INVALID_HANDLE_VALUE) {
 printf("Error %d.\n", GetLastError());
 exit(EXIT_FAILURE);
 }

 GetFullPathName(structFData.cFileName, MAX_PATH, tszBuffer, NULL);

 printf("%s \n%s\n\n", tszBuffer, structFData.cFileName);

 FindClose(hFindFile);

 return 0;
}

Please note that the GetFullPathName() function is not recommended for multi-threaded programs.

Advertisements

Files and Directories using win32

The CreateDirectory() function is used to create a new directory. It takes two arguments, the first is the directory name, and the second is the security settings for the new directory. The RemoveDirectory() function deletes directories. It takes only one argument, the path of the directory to be deleted.

#include <stdio.h>
#include <Windows.h>

int _tmain(int argc, _TCHAR* argv[])
{
	char name[56] = "aDirectory";

	if(CreateDirectory(name, NULL)){
		printf("Directory %s created.\n", name);
	}

	if(RemoveDirectory(name)){
		printf("Directory %s removed.\n", name);
	}

	return 0;
}

We can use the GetFileAttributes() function to make sure a file or directory exists.

#include <stdio.h>
#include <Windows.h>

bool CheckIfFileObjectExists(const char *filename);
bool CheckIfDirectory(const char *filename);
bool CheckIfFile(const char *filename);

int _tmain(int argc, _TCHAR* argv[])
{
	HANDLE hFile;
	char dirName[56] = "TestDirectory";
	char fileName[56] = "TestFile.txt";

	if(CheckIfFileObjectExists(dirName)){
		printf("File object '%s' exists.\n", dirName);
		if(CheckIfDirectory(dirName)){
			printf("It is a directory.\n");
		}
	} else {
		printf("Directory '%s' does not exist.\n", dirName);
		CreateDirectory(dirName, NULL);
	}

	hFile = CreateFile(fileName, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);

	if(hFile == INVALID_HANDLE_VALUE){
		printf("Error creating file %s\n", fileName);
	} else {
		printf("File %s created.\n", fileName);
		CloseHandle(hFile);
	}

	if(CheckIfFileObjectExists(fileName)){
		printf("%s exists.\n", fileName);
		if(CheckIfDirectory(fileName)){
			printf("%s is a directory.\n", fileName);
		} else {
			printf("%s is not a directory.\n", fileName);
		}
		if(CheckIfFile(fileName)){
			printf("%s is a file.\n", fileName);
			printf("Deleting file now...");
			DeleteFile(fileName);
		}
	}

	return 0;
}

bool CheckIfFileObjectExists(const char *filename){
	DWORD dwAttributes = GetFileAttributes(filename);
	return (bool)(dwAttributes != INVALID_FILE_ATTRIBUTES);
}

bool CheckIfDirectory(const char *filename){
	DWORD dwAttributes = GetFileAttributes(filename);
	return (bool)(dwAttributes & FILE_ATTRIBUTE_DIRECTORY);
}

bool CheckIfFile(const char *filename){
	DWORD dwAttributes = GetFileAttributes(filename);
	return (bool)!(dwAttributes & FILE_ATTRIBUTE_DIRECTORY);
}

The FindFirstFile() function searches through a directory for a given file. Since the FindFirstFile() function accepts a wildcard, we can use it to list all the files in a directory. The FindFirstFile() function takes two arguments, the first of which is the file to find, the second of which is a pointer to a WIN32_FIND_DATA structure.

If the FindFirstFile() function executes successfully, we get a search handle that can be used in subsequent find operations. If FindFirstFile() fails, we get an INVALID_HANDLE_VALUE returned.

The FindNextFile() is used to continue a search. The FindNextFile() function returns true if it finds another file, and false if it doesn’t.

#include <Windows.h>
#include <stdio.h>

void listDirectoryContents(const char *filename);

int _tmain(int argc, _TCHAR* argv[])
{
	listDirectoryContents("C:\\Users\\AL");
	listDirectoryContents("C:\\Users\\AL\\Downloads");
	return 0;
}

void listDirectoryContents(const char *filename){

	DWORD dwAttrib = GetFileAttributes(filename);
	//note negation operator
	if(!(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)){
		printf("%s is not a directory", filename);
		return;
	}

	//create search filename with wildcard (*)
	char buffer[256];
	sprintf_s(buffer, "%s\\*", filename);

	LARGE_INTEGER unionFilesize;
	WIN32_FIND_DATA structWFD;
	HANDLE hSrch = FindFirstFile(buffer, &structWFD);

	if(hSrch == INVALID_HANDLE_VALUE){
		printf("Error %x\n", GetLastError);
		return;
	}

	printf("\nFiles in %s:\n", filename);

	if(structWFD.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY){
		printf("%s \t (directory)\n", structWFD.cFileName);
	} else {
		//get filesize
		unionFilesize.HighPart = structWFD.nFileSizeHigh;
		unionFilesize.LowPart = structWFD.nFileSizeLow;
		printf("%s \t %lld bytes\n", structWFD.cFileName, unionFilesize.QuadPart);
	}

	while(FindNextFile(hSrch, &structWFD)!=0){
		if(structWFD.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY){
			printf("%s \t (directory)\n", structWFD.cFileName);
		} else {
			unionFilesize.HighPart = structWFD.nFileSizeHigh;
			unionFilesize.LowPart = structWFD.nFileSizeLow;
			printf("%s \t %lld bytes\n", structWFD.cFileName, unionFilesize.QuadPart);
		}
	}

	FindClose(hSrch);

}

The FindClose() function is used to close the search handle. It’s a good idea to explicitly close the handle.