VC下文件的使用

Posted zeqi1991

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了VC下文件的使用相关的知识,希望对你有一定的参考价值。

在VC下文件的使用的案例

文件常用的有新建,读,写文件,删除文件,读取文件的路径,创建文件夹(目录),文件的复制,移动,重命名,读取文件的大小,

查找文件,遍历目录下的文件和子目录,递归遍历目录下的所有文件和子目录

比较少用到的的功能设置文件的属性,使用内存映射文件等


下面是几个关于文件使用几个函数 : 

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


//创建文件
HANDLE CreateFile( __in LPCSTR lpFileName,                 
	__in DWORD dwDesiredAccess, 						   
	__in DWORD dwShareMode, 							   
	__in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes,   
	__in DWORD dwCreationDisposition, 					   
	__in DWORD dwFlagsAndAttributes, 					   
	__in_opt HANDLE hTemplateFile );					   
//参数
//lpFileName			  //操作对象文件的相对或者绝对路径
//dwDesiredAccess		  //指明对象文件的操作存取方式 GENERIC_READ, GENERIC_WRITE, GENERIC_READGENERIC_WRITE
//dwShareMode			  //指明与其他进程是否共享该文件,可以读,写,删除共享等FILE_SHARE_WRITE, 如果进程独占改文件,设置为0
//lpSecurityAttributes	  //表示文件句柄的安全属性,一般设置为NULL,有特殊要求特别设置
//dwCreationDisposition	  //文件操作模式 CREATE_ALWAYS, CREATE_NEW, OPEN_ALWAYS, OPEN_EXISTING, TRUNCATE_EXISTING
//dwFlagsAndAttributes	  //文件属性和标志, 一般设置为FILE_ATTRIBUTE_NORMAL
//hTemplateFile			  //当存取权限包括GENERIC_WRITE, 可以设置一个模板文件的句柄.一般设置为NULL



HANDLE hFile = CreateFile(".\\setting.txt", GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);


//从文件中读取数据
BOOL ReadFile(__in        HANDLE hFile,																	         
	__out_bcount_part_opt(nNumberOfBytesToRead, *lpNumberOfBytesRead) __out_data_source(FILE) LPVOID lpBuffer,   
	__in        DWORD nNumberOfBytesToRead,																	     
	__out_opt   LPDWORD lpNumberOfBytesRead,																	 
	__inout_opt LPOVERLAPPED lpOverlapped);																	     
//参数
//hFile				文件句柄,文件操作方式应该是GENERIC_READ
//lpBuffer			读取文件数据存储数据的内存缓冲区
//nNumberOfBytesToRead 指明需要需要从文件中读出的数据的大小,不能大于lpBuffer的大小,否则会溢出
//lpNumberOfBytesRead输出参数,指向存储实际独处的数据大小DWORD变量
//lpOverlapped:输出参数,如果抵用CreateFile函数设置了FILE_FLAG_OVERLAPPED标志,则需要使用该参数,否则可以为NULL

//从文件中写入数据
BOOL WriteFile( __in HANDLE hFile,                   					
	__in_bcount_opt(nNumberOfBytesToWrite) LPCVOID lpBuffer,			
	__in DWORD nNumberOfBytesToWrite, 									
	__out_opt LPDWORD lpNumberOfBytesWritten, 							
	__inout_opt LPOVERLAPPED lpOverlapped );	     					
//参数
//hFile					  文件句柄
//lpBuffer				  需要写入文件的缓冲区
//nNumberOfBytesToWrite	  指明需要写入文件中的数据的大小
//lpNumberOfBytesWritten  指向真是写入的数据大小的变量
//lpOverlapped:输出参数,如果抵用CreateFile函数设置了FILE_FLAG_OVERLAPPED标志,则需要使用该参数,否则可以为NULL


//获取文件的大小
DWORD GetFileSize(HANDLE hFile, LPDWORD lpFilesizeHigh);
//参数
//HANDLE hFile 文件句柄
//LPDWORD lpFilesizeHigh 输出函数, 表示得到的文件大小的高32位,该参数可以设置为NULL
//还有一个获取文件大小的函数 BOOL GetFileSizeEx(HANDLE hFile, PLARGE_INTEGER lpFileSize);


//删除文件
BOOL DeleteFile( LPCTSTR lpFileName );
//参数  LPCTSTR lpFileName 表示要删除文件的相对路径或绝对路径
//返回值BOOL 表示文件删除是否成功,如果程序返回失败,可以用GetLastError()获取错误信息

//复制文件
BOOL CopyFile(LPCTSTR lpExistingFileName, LPCTSTR lpNewFileName, BOOL bFailIfExists);
//参数 
//lpExistingFileName : 已经存在的所需复制文件的原路径
//lpNewFilename : 新文件路径,复制文件的目的路径
//bFailIfExists : 指明如果在目的路径存在文件时是否覆盖,如果设置为TRUE,则不覆盖,如果存在,则返回失败(0x50)

//移动文件(该函数的功能 : 移动,重命名和目录)
BOOL MoveFile(LPCTSTR lpExistingFileName, LPCTSTR lpNewFileName);
//参数 
//lpExistingFileName : 已经存在的所需移动文件的原路径
//lpNewFilename : 新文件路径,移动文件的目的路径

//CopyFileEx, MoveFileEx, MoveFileWithProcessSS函数功能更加丰富


//创建一个目录或者文件夹
BOOL CreateDirectory( LPCTSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes );
//lpPathName : 所需要创建的目录或者路径
//lpSecurityAttributes : 输入参数,设置为NULL
//返回值 如果失败,可以使用GetLastError函数获取错误信息, 
//可能的值包括ERROR_ALREADY_EXISTS(文件已经存在), ERROR_PATH_NOT_FOUND

//获取进程的当前目录
DWORD GetCurrentDirectory( DWORD nBufferLength, LPTSTR lpBuffer );
//参数
//nBufferLength : 输入参数,存储路径字符串缓冲区的大小,一般调用MAX_PATH
//lpBuffer: 输出参数,只想获取的路径字符串
//返回值 : 如果为0,表示失败。 如果非0,表示获取的字符串的长度

//设置进程的当前目录
BOOL SetCurrentDirectory(LPCTSTR lpPathName);
//参数
//lpPathName : 输入参数,所要设置的路径


//获取模块文件名
DWORD GetModuleFileName( __in_opt HMODULE hModule, 								
	                     __out_ecount_part(nSize, return + 1) LPSTR lpFilename,	
						 __in DWORD nSize );

//hModule : 所需要模块路径的模块句柄,设置为NULL表示当前模块路径
//lpFilename: 模块的全路径
//nSize : 指向缓冲区的大小

//返回值 : 如果为0,表示失败。 如果非0,表示获取的字符串的长度


//对文件进行查找,遍历指定目录下的文件和子目录
//WINDOW api中,有一组专门的函数和数据结构,用于遍历目录, 
//他们是FindFirstFile, FindNextFile, WIN32_FIND_DATA
BOOL FindNextFile( __in HANDLE hFindFile,
				   __out LPWIN32_FIND_DATAA lpFindFileData );
//hFindFile  查找的目录,需使用通配符指定查找的文件目标
//lpFindFileData 指向WIN32_FIND_DATA结构的指针,为找到的文件及若干属性信息

HANDLE FindFirstFile( __in LPCSTR lpFileName,
	                  __out LPWIN32_FIND_DATAA lpFindFileData );
//lpFileName 查找句柄
//lpFindFileData 指向WIN32_FIND_DATA结构的指针,为找到的文件及若干属性信息

//关键的结构体

typedef struct _WIN32_FIND_DATAA {
	DWORD dwFileAttributes;
	FILETIME ftCreationTime;
	FILETIME ftLastAccessTime;
	FILETIME ftLastWriteTime;
	DWORD nFileSizeHigh;
	DWORD nFileSizeLow;
	DWORD dwReserved0;
	DWORD dwReserved1;
	CHAR   cFileName[ MAX_PATH ];
	CHAR   cAlternateFileName[ 14 ];
#ifdef _MAC
	DWORD dwFileType;
	DWORD dwCreatorType;
	WORD  wFinderFlags;
#endif
} WIN32_FIND_DATAA, *PWIN32_FIND_DATAA, *LPWIN32_FIND_DATAA;

//实现对指定目录中文件和子目录的遍历,并将遍历得到的文件和其他属性打印到界面上
DWORD EnumerateFileInDirectory(LPSTR szPath)
{
	WIN32_FIND_DATA FindFileData;
	HANDLE hListFile;
	CHAR szFilePath[MAX_PATH];

	//构造代表子目录和文件夹路径的字符串,使用通配符"*"
	lstrcpy(szFilePath, szPath);
	//注释的代码可以用于查找所有的以".txt"结尾的文件
	//lstrcat(szFilePath, "\\*.txt");
	lstrcat(szFilePath, "\\*");
	//查找第一个文件/目录, 获取查找句柄
	hListFile = FindFirstFile(szFilePath, &FindFileData);
	if (hListFile == INVALID_HANDLE_VALUE)
	{
		return 1;
	}
	else
	{
		do 
		{
			/*如果不想显示代表本级目录和上一级目录的"."和".."
			可以使用注释部分的代码过滤
			if (lstrcmp(FindFileData.cFileName, TEXT(".")) == 0 || lstrcmp(FindFileData.cFileName, TEXT("..")) == 0)
			{
				continue;
			}
			*/
			//打印文件名,目录名
			printf("%s\t\t", FindFileData.cFileName);

			//判断文件属性,是否为加密文件或文件夹
			if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED)
			{
				printf("加密\n");
			}
			//判断文件属性是否为隐藏文件或文件夹
			if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
			{
				printf("隐藏\n");
			}
			//判断文件属性是否为目录
			if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
			{
				printf("DIR");
				//如果是目录,可以继续查找下去
				CHAR szNewFilePath[MAX_PATH] = {9};
				wsprintf(szNewFilePath, "%s\\%s", szPath, FindFileData.cFileName);
				EnumerateFileInDirectory(szNewFilePath);
			}
		} while (FindNextFile(hListFile, &FindFileData));
	}
	return 0;
}


/*************************************************************
SaveDataToFile
功能 : 读取文件内容
参数 : LPSTR szFilePath       文件路径
**************************************************************/
DWORD ReadFileContent(LPSTR szFilePath)
{
	//文件句柄
	HANDLE hFileRead = NULL;
	//保持文件大小
	LARGE_INTEGER liFileSize;
	//成功读取文件数据大小
	DWORD dwReadedSize;
	//累加计算已经读取数据大小
	LONGLONG liTotalRead = 0;
	//文件数据缓存
	BYTE lpFileDataBuffer[32] = {0};

	//打开已有文件,读取内容
	hFileRead = CreateFile(szFilePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

	//打开文件是否成功
	if (hFileRead == INVALID_HANDLE_VALUE)
	{
		printf("打开文件失败 : %d\n", GetLastError());
		return 0;
	}
	if (!GetFileSizeEx(hFileRead, &liFileSize))
	{
		printf("获取文件大小失败 : %d\n", GetLastError());
		return 0;
	}
	else
	{
		printf("文件大小为 : %d\n", liFileSize.QuadPart);
	}
	
	//循环读取文件并打印文件内容
	while (1)
	{
		DWORD i;
		if (!ReadFile(hFileRead, lpFileDataBuffer, 32, &dwReadedSize, NULL))
		{
			printf("读取文件错误 : %d\n", GetLastError());
		}
		printf("读取了%d 个字节, 文件内容是 : ", dwReadedSize);
		for (i = 0; i < dwReadedSize; i++)
		{
			printf("0x%x", lpFileDataBuffer[i]);
		}
		printf("\n");
		liTotalRead += dwReadedSize;
		if (liTotalRead == liFileSize.QuadPart)
		{
			printf("文件读取结束!\n");
			break;
		}
	}
	CloseHandle(hFileRead);
	return 1;
}

/*************************************************************
SaveDataToFile
功能 : 将数据存储到文件末尾
参数 : LPSTR szFilePath       文件路径
	   LPVOID lpData          需存储的数据
	   DWORD dwDataSize       数据大小(字节)
**************************************************************/
DWORD SavaDataToFile(LPSTR szFilePath, LPVOID lpData, DWORD dwDataSize)
{
	//文件句柄
	HANDLE hFileWrite = NULL;
	//成功写入的数据大小
	DWORD dwWriteDataSize = 0;
	//打开已经存在的文件,读取内容
	hFileWrite = CreateFile(szFilePath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	if (hFileWrite == INVALID_HANDLE_VALUE)
	{
		printf("打开文件失败 : %d\n", GetLastError());
		return 0;
	}
	//设置文件指针到文件尾
	SetFilePointer(hFileWrite, 0, 0, FILE_END);
	//将数据写入文件
	if (!WriteFile(hFileWrite, lpData, dwDataSize, &dwWriteDataSize, NULL))
	{
		printf("写入文件失败 : %d\n", GetLastError());
		return 0;
	}
	else
	{
		printf("写入文件成功, 写入 %d 个字节!\n", dwWriteDataSize);
	}
	CloseHandle(hFileWrite);
	return 1;
}


//ini文件的测试代码
void TestINIFile()
{
	//在当前程序目录下创建一个user_setting.ini文件
	HANDLE hFile = NULL;
	hFile = CreateFile(".\\user_setting.ini", GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	if (NULL == hFile)
	{
		printf("文件创建失败!\n");
		return;
	}
	CloseHandle(hFile);

	//在user_setting.ini文件中创建一个section,并写入数据
	BOOL bRet = FALSE;
	bRet = WritePrivateProfileString("Column_Section", "Column_Width", "500", ".\\user_setting.ini");
	bRet = WritePrivateProfileString("Column_Section", "Column_Height", "500", ".\\user_setting.ini");
	bRet = WritePrivateProfileString("Column_Section", "Column_Angle", "0.0", ".\\user_setting.ini");
	bRet = WritePrivateProfileString("Column_Attribute", "Column_Id", "1", ".\\user_setting.ini");
	bRet = WritePrivateProfileString("Column_Attribute", "Column_Color", "Red", ".\\user_setting.ini");
	bRet = WritePrivateProfileString("Column_Attribute", "Column_Point", "Original", ".\\user_setting.ini");
	//从user_setting.ini文件中读取某个section的一个key的字符串
	CHAR Column_Width[100] = {0};
	DWORD dwRes = 0;
	dwRes = GetPrivateProfileString("Column_Section", "Column_Width", "300", Column_Width, 100, ".\\user_setting.ini");
	CHAR Column_Height[100] = {0};
	dwRes = GetPrivateProfileString("Column_Section", "Column_Width", "300", Column_Height, 100, ".\\user_setting.ini");
	CHAR Column_Angle[100] = {0};
	dwRes = GetPrivateProfileString("Column_Section", "Column_Width", "300", Column_Angle, 100, ".\\user_setting.ini");

	//从ini文件中读取整个section的内容
	CHAR Column_Attribute[300] = {0};
	dwRes = GetPrivateProfileSection("Column_Attribute", Column_Attribute, 300, ".\\user_setting.ini");
	printf("%s\n", Column_Attribute);
	//从ini文件中读取section的名称, 如果 ini 中有两个 Section: [sec1] 和 [sec2],则返回的是 'sec1',0,'sec2',0,0
	CHAR Section_Name[100] = {0};
	dwRes = GetPrivateProfileSectionNames(Section_Name, 100, ".\\user_setting.ini");
	printf("%s\n", Section_Name);

	//将一个整个section的内容加入到另外指定的section中, Column_Attribute中的内容覆盖了原来Column_Section中的内容
	bRet = WritePrivateProfileSection("Column_Section", Column_Attribute, ".\\user_setting.ini");
}

//获取当前目录,获取程序所在的目录,获取模块路径
void TestOnDirectory()
{
	//用于储存当前路径
	CHAR szCurrentDirectory[MAX_PATH] = {0};
	//用于储存模块路径
	CHAR szMoudlePath[MAX_PATH] = {0};
	//Kernel32文件名与句柄
	LPSTR szKernel32 = "kernel32.dll";
	HMODULE hKernel32;
	//当前路径的长度,也用于判断获取是否成功
	DWORD dwCurDirPathLen;
	//获取进程的当前目录
	dwCurDirPathLen = GetCurrentDirectory(MAX_PATH, szCurrentDirectory);
	if (dwCurDirPathLen == 0)
	{
		return;
	}
	printf("%s\n", szCurrentDirectory);

	//将进程当前的目录设置为 "C:\"
	lstrcpy(szCurrentDirectory, "C:\\");
	if (!SetCurrentDirectory(szCurrentDirectory))
	{
		return;
	}

	//在当前目录下创建子目录“current_dir"
	CreateDirectory("current_dir", NULL);

	//再次获取系统当前目录
	dwCurDirPathLen = GetCurrentDirectory(MAX_PATH, szCurrentDirectory);
	if (dwCurDirPathLen == 0)
	{
		return;
	}
	printf("GetCurrentDirectory获取的当前目录为 %s\n", szCurrentDirectory);

	//使用NULL参数,获取本模块的路径
	if (!GetModuleFileName(NULL, szMoudlePath, MAX_PATH))
	{
		return;
	}
	printf("本模块路径 %s", szMoudlePath);

	//获取Kernel32.dll的模块句柄
	hKernel32 = LoadLibrary(szKernel32);

	//获取kernel32.dll的模块句柄
	if (!GetModuleFileName(hKernel32, szMoudlePath, MAX_PATH))
	{
		return;
	}
	printf("kernel32.dll模块路径 %s", szMoudlePath);

	return;
}

//对文件的属性进行显示的一些函数

DWORD ShowFileTime(PFILETIME lptime);
DWORD ShowFileSize(DWORD dwFileSizeHigh, DWORD dwFileSizeLow);
DWORD ShowFileAttrInfo(DWORD dwAttribute);
DWORD ShowFileAttribute(LPSTR szPath)
{
	WIN32_FILE_ATTRIBUTE_DATA wfad;
	printf("文件 : %s\n", szPath);
	//获取文件属性
	if (!GetFileAttributesEx(szPath, GetFileExInfoStandard, &wfad))
	{
		return 1;
	}
	//显示相关信息
	printf("创建时间 : \t");
	ShowFileTime(&(wfad.ftCreationTime));
	printf("最后访问时间 : \t");
	ShowFileTime(&(wfad.ftLastAccessTime));
	printf("最后修改时间 : \t");
	ShowFileTime(&(wfad.ftLastWriteTime));
	
	//显示文件的大小
	ShowFileSize(wfad.nFileSizeHigh, wfad.nFileSizeLow);
	//显示文件属性
	ShowFileAttrInfo(wfad.dwFileAttributes);
	return 0;
}

DWORD ShowFileTime(PFILETIME lptime)
{
	//文件时间结构
	FILETIME ftLocal;
	//系统时间结构
	SYSTEMTIME st;
	//调整为系统所在时区的时间
	FileTimeToLocalFileTime(lptime, &ftLocal);
	//将文件时间格式转换
	FileTimeToSystemTime(&ftLocal, &st);
	//显示时间字符
	printf("%4d year  %2d month  %2d day, %#02d:%#02d:%#02d\n", st.wYear, st.wMonth, st.wDay, st.wMinute, st.wSecond);
	return 0;
}
DWORD ShowFileSize(DWORD dwFileSizeHigh, DWORD dwFileSizeLow)
{
	ULONGLONG liFilesize;
	liFilesize = dwFileSizeHigh;
	//移动到32位
	liFilesize <<= sizeof(DWORD) * 8;
	liFilesize += dwFileSizeLow;
	printf("文件大小 : \t%I64u字节\n", liFilesize);
	return 0;
}
DWORD ShowFileAttrInfo(DWORD dwAttribute)
{
	//一次判断文件的属性并显示
	printf("文件属性 : \t");
	if (dwAttribute & FILE_ATTRIBUTE_ARCHIVE)
	{
		printf("ARCHIVE\N");
	}
	if (dwAttribute & FILE_ATTRIBUTE_COMPRESSED)
		printf("压缩文件");
	if (dwAttribute & FILE_ATTRIBUTE_DIRECTORY)
		printf("目录文件");
	if (dwAttribute & FILE_ATTRIBUTE_ENCRYPTED)
		printf("加密文件");
	if (dwAttribute & FILE_ATTRIBUTE_HIDDEN)
		printf("隐藏文件");
	if (dwAttribute & FILE_ATTRIBUTE_NORMAL)
		printf("Normal");
	if (dwAttribute & FILE_ATTRIBUTE_OFFLINE)
		printf("OFFLINE");
	if (dwAttribute & FILE_ATTRIBUTE_READONLY)
		printf("只读文件");
	if (dwAttribute & FILE_ATTRIBUTE_SPARSE_FILE)
		printf("sparse");
	if (dwAttribute & FILE_ATTRIBUTE_SYSTEM)
		printf("系统文件");
	if (dwAttribute & FILE_ATTRIBUTE_TEMPORARY)
		printf("临时文件");
	printf("\n");
	return 0;
}

//给文件添加其他属性
DWORD SetFileHiddenAndReadOnly(LPSTR szFileName)
{
	//获取原来的属性
	DWORD dwFileAttributes = GetFileAttributes(szFileName);
	//添加
	dwFileAttributes |= FILE_ATTRIBUTE_READONLY;
	dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN;
	//设置文件属性,并判断是否成功
	if (SetFileAttributes(szFileName, dwFileAttributes))
	{
		printf("文件 %s 的隐藏和属性设置成功\n", szFileName);
	}
	else
	{
		printf("文件设置失败 %d\n", GetLastError());
	}
	return 0;
}

//对文件进行复制,删除,移动
int main(int argc, PCHAR argv[])
{
	if (0 == lstrcmp("-d", argv[1]) && argc == 3)
	{
		if (!DeleteFile(argv[2]))
		{
			printf("删除文件错误!\n");
			return 1;
		}
		else
		{
			printf("删除文件成功!\n");
		}
	}
	else if (0 == lstrcmp("-c", argv[1]) && argc == 4)//复制文件
	{
		if (!CopyFile(argv[2], argv[3], TRUE))
		{
			//lastError == 0X50,文件存在
			if (GetLastError() == 0x50)
			{
				printf("文件已经存在,是否覆盖? Y/N", argv[3]);
				if ('y' == getchar())
				{
					//复制,覆盖已经存在的文件
					if (!CopyFile(argv[2], argv[3], FALSE))
					{
						printf("复制文件错误!\n");
					}
					else
					{
						printf("复制成功!\n");
					}
				}
				else
					return 0;
			}
		}
	}
	else if (0 == lstrcmp("-m", argv[1]) && argc == 4)
	{
		if (!MoveFile(argv[2], argv[3]))
		{
			printf("移动文件错误\n");
		}
		else
		{
			printf("参数错误!\n");
		}
	}
		
	return 0;
}





以上是关于VC下文件的使用的主要内容,如果未能解决你的问题,请参考以下文章

使用 VC++ 删除文件夹的内容

vc下如何设置pe文件图标为系统文件夹图标?不是设置,是不带ico的,直接获取的.

在Tomcat的安装目录下conf目录下的server.xml文件中增加一个xml代码片段,该代码片段中每个属性的含义与用途

C/C++编程笔记:VC++6.0环境下调试 C语言 代码的方法和步骤

VC ++ WINAPI窗体:找不到标识符(C3861错误)

VC下文件的使用