得到当前文件路径
GetCurrentDirectory();
//获取当前进程的当前目录。
DWORD GetCurrentDirectory(DWORD nBufferLength, //缓冲区的长度
LPTSTR lpBuffer); //指定一个预定义字串,用于保存当前目录
代码演示
TCHAR strArr[1024] = {};
//WndProc消息处理函数中
switch (message)
{
//鼠标的左键按下
case WM_LBUTTONDOWN:
{
//得到当前的工作路径
GetCurrentDirectory(1023,strArr);
Message(0,strArr,0,0);
}
break;
}
得到临时路径
GetTempPath();
临时路径是由TMP环境变量指定的一个路径。如TMP不存在,则是由TEMP环境变量指定的路径。如果这两个环境变量都不存在,就是当前目录。
通过把资源文件解包到临时文件夹,然后在临时文件夹中读取程序所需资源文件,因为win32 GDI不支持从内存地址中获取资源文件。
//获取为临时文件指定的路径
DWORD GetTempPath(DWORD nBufferLength, //缓冲区的长度
LPTSTR lpBuffer); //指定一个预定义字串,用于保存当前目录
代码演示
//通过把资源文件解包到临时文件夹,然后在临时文件夹中读取程序所需资源文件
TCHAR strArr[1024] = {};
//WndProc消息处理函数中
switch (message)
{
//鼠标的左键按下
case WM_LBUTTONDOWN:
{
//得到当前的工作路径
GetTempPath(1023,strArr);
Message(0,strArr,0,0);
}
break;
}
打开或者创建新文件
CreateFile()//打开或新建文件
//打开或新建文件
HANDLE CreateFile(_In_ LPCTSTR lpFileName, //要打开的文件的名或设备名
_In_ DWORD dwDesiredAccess, //文件访问权限
_In_ DWORD dwShareMode, //共享权限
_In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,//定义了文件的安全特性
_In_ DWORD dwCreationDisposition,//文件打开或者创建方式
_In_ DWORD dwFlagsAndAttributes, //文件属性
_In_opt_ HANDLE hTemplateFile); //文件模板属性
参数说明
lpFileName String要打开的文件的名或设备名。这个字符串的最大长度在ANSI版本中为MAX_PATH,在unicode版本中为32767。
dwDesiredAccess指定类型的访问对象。如果为 GENERIC_READ 表示允许对设备进行读访问;如果为 GENERIC_WRITE 表示允许对设备进行写访问(可组合使用);如果为零,表示只允许获取与一个设备有关的信息 。
另外,还可以指定下面的控制标志:
标准控制权限(16-23位掩码):
值 | 描述 |
---|---|
DELETE | 删除对象的权限。 |
READ_CONTROL | 从对象的安全描述符中读取信息的权限,但不包括SACL(系统访问控制列表)中的信息。 |
WRITE_DAC | 修改对象安全描述符中的DACL(随机访问控制列表)的权限 |
WRITE_OWNER | 修改对象安全描述符中的属主的权限 |
SYNCHRONIZE | 同步化使用对象的权限,即可以创建一个线程等待信号量释放(但有些对象不支持这个权限)。 |
STANDARD_RIGHTS_REQUIRED | 等价于前面四种权限的总合(通常这四种是必须具有的权限)。 |
STANDARD_RIGHTS_READ | 一般等价于READ_CONTROL |
STANDARD_RIGHTS_WRITE | 一般等价于READ_CONTROL |
STANDARD_RIGHTS_EXECUTE | 一般等价于READ_CONTROL |
STANDARD_RIGHTS_ALL | 等价于前面五种权限的总合。 |
特殊控制权限(0-15位掩码):
值 | 描述 |
---|---|
SPECIFIC_RIGHTS_ALL | |
ACCESS_SYSTEM_SECURITY | |
MAXIMUM_ALLOWED | |
GENERIC_READ | 文件只读 |
GENERIC_WRITE | 文件只写 |
GENERIC_EXECUTE | 文件一直存在用此属性 |
GENERIC_ALL | 文件可读写 |
注:实质上是通过ACCESS_MASK结构体的一个双字值来设置标准权限、特殊权限和一般权限的。
dwShareModeLong, 文件共享属性,值如下:
值 | 描述 |
---|---|
0 | 如果是零表示不共享; |
FILE_SHARE_DELETE | 表示随后打开操作对象会成功,但只有删除访问请求的权限; |
FILE_SHARE_READ | 随后打开操作对象会成功只有请求读访问的权限; |
FILE_SHARE_WRITE | 随后打开操作对象会成功,但只有请求写访问的权限。 |
lpSecurityAttributesSECURITY_ATTRIBUTES, 指向一个SECURITY_ATTRIBUTES结构的指针,定义了文件的安全特性(如果操作系统支持的话),一般赋值为NULL;
dwCreationDispositionLong,下述常数之一:
值 | 描述 |
---|---|
CREATE_NEW | 创建文件;如文件存在则会出错 |
CREATE_ALWAYS | 创建文件,会改写前一个文件 |
OPEN_EXISTING | 文件必须已经存在。由设备提出要求 |
OPEN_ALWAYS | 如文件不存在则创建它 |
TRUNCATE_EXISTING | 将现有文件缩短为零长度 |
dwFlagsAndAttributesLong, 一个或多个下述常数
值 | 描述 |
---|---|
FILE_ATTRIBUTE_ARCHIVE | 标记归档属性 |
FILE_ATTRIBUTE_COMPRESSED | 将文件标记为已压缩,或者标记为文件在目录中的默认压缩方式 |
FILE_ATTRIBUTE_NORMAL | 默认属性 |
FILE_ATTRIBUTE_HIDDEN | 隐藏文件或目录 |
FILE_ATTRIBUTE_READONLY | 文件为只读 |
FILE_ATTRIBUTE_SYSTEM | 文件为系统文件 |
FILE_FLAG_WRITE_THROUGH | 操作系统不得推迟对文件的写操作 |
FILE_FLAG_OVERLAPPED | 允许对文件进行重叠操作 |
FILE_FLAG_NO_BUFFERING | 禁止对文件进行缓冲处理。文件只能写入磁盘卷的扇区块 |
FILE_FLAG_RANDOM_ACCESS | 针对随机访问对文件缓冲进行优化 |
FILE_FLAG_SEQUENTIAL_SCAN | 针对连续访问对文件缓冲进行优化 |
FILE_FLAG_DELETE_ON_CLOSE | 关闭了上一次打开的句柄后,将文件删除。特别适合临时文件 |
也可在Windows NT下组合使用下述常数标记:
SECURITY_ANONYMOUS, SECURITY_IDENTIFICATION, SECURITY_IMPERSONATION, SECURITY_DELEGATION, SECURITY_CONTEXT_TRACKING, SECURITY_EFFECTIVE_ONLY
hTemplateFile,hTemplateFile为一个文件或设备句柄,表示按这个参数给出的句柄为模板创建文件(就是将该句柄文件拷贝到lpFileName指定的路径,然后再打开)。它将指定该文件的属性扩展到新创建的文件上面,这个参数可用于将某个新文件的属性设置成与现有文件一样,并且这样会忽略dwAttrsAndFlags。通常这个参数设置为NULL,为空表示不使用模板,一般为空。
文件读写
文件读写不能用宽字节,如果用了宽字节,需要自己做转换。
WriteFile() 写文件
//写文件
BOOL WriteFile(HANDLE hFile, //文件句柄
LPCVOID lpBuffer,//数据缓存区指针
DWORD nNumberOfBytesToWrite,//你要写的字节数
LPDWORD lpNumberOfBytesWritten,//用于保存实际写入字节数的存储区域的指针
LPOVERLAPPED lpOverlapped//OVERLAPPED结构体指针);
从文件指针指向的位置开始将数据写入到一个文件中, 且支持同步和异步操作,
如果文件打开方式没有指明FILE_FLAG_OVERLAPPED的话,当程序调用成功时,它将实际写入文件的字节数保存到lpNumberOfBytesWriten指明的地址空间中。
如果文件要交互使用的话,当函数调用完毕时要记得调整文件指针。
参数说明
HANDLE hFile, 需要写入数据的文件指针,这个指针指向的文件必须是GENERIC_WRITE access 访问属性的文件
LPOVERLAPPED lpOverlapped OVERLAPPED结构体指针,如果文件是以FILE_FLAG_OVERLAPPED方式打开的话,那么这个指针就不能为NULL
vc返回值
调用成功,返回非0
调用不成功,返回为0
ReadFile() 读文件
//读取文件
BOOL ReadFile(HANDLE hFile,//文件的句柄
LPVOID lpBuffer,//用于保存读入数据的一个缓冲区
DWORD nNumberOfBytesToRead,//要读入的字节数
LPDWORD lpNumberOfBytesRead,//指向实际读取字节数的指针
LPOVERLAPPED lpOverlapped);//如文件打开时指定了FILE_FLAG_OVERLAPPED,那么必须,用这个参数引用一个特殊的结构。//该结构定义了一次异步读取操作。否则,应将这个参数设为NULL
/*FILE_FLAG_OVERLAPPED
文件或设备被打开或创建异步I / O。
当后续的I / O操作完成这个句柄,OVERLAPPED结构中指定的事件 将被设置为有信号状态。
如果这个标志被指定,该文件可用于同时读取和写入操作。
如果没有指定这个标志,然后被序列化I / O操作,即使调用读写函数指定一个OVERLAPPED结构。*/
参数说明
HANDLE hFile, 需要读入数据的文件指针,这个指针指向的文件必须是GENERIC_READ 访问属性的文件。
LPVOID lpBuffer,接收数据的缓冲区。
DWORD nNumberOfBytesToRead,指定要读取的字节数。
LPDWORD lpNumberOfBytesRead,指向一个DWORD类型变量的指针,用来接收读取的字节数。如果下一个参数为NULL,那么一定要传入这个参数。
LPOVERLAPPED lpOverlapped OVERLAPPED结构体指针,如果文件是以FILE_FLAG_OVERLAPPED方式打开的话,那么这个指针就不能为NULL。
FILE_FLAG_OVERLAPPED 允许对文件进行重叠操作
调用成功,返回非0
调用不成功,返回为0
会设置GetLastError。如启动的是一次异步读操作,则函数会返回零值,并将ERROR_IO_PENDING设置成GetLastError的结果。如结果不是零值,但读入的字节数小于nNumberOfBytesToRead参数指定的值,表明早已抵达了文件的结尾。
设置文件中的读取位置
SetFilePointer() 在一个文件中设置新的读取位置。
DWORD SetFilePointer(HANDLE hFile, //文件句柄
LONG lDistanceToMove, //偏移量(低位)
PLONG lpDistanceToMoveHigh,//偏移量(高位)
DWORD dwMoveMethod); //基准位置
参数 类型及说明
hFile系统文件句柄
lDistanceToMove Long,字节偏移量
lpDistanceToMoveHigh Long,指定一个长整数变量,其中包含了要使用的一个高双字偏移。可设为零(将声明变为ByVal),表示只使用lDistanceToMove
dwMoveMethod Long,下述值之一
值 | 描述 |
---|---|
FILE_BEGIN | 将新位置设为从文件起始处开始算的起的一个偏移 |
FILE_CURRENT | 将新位置设为从当前位置开始计算的一个偏移 |
FILE_END | 将新位置设为从文件尾开始计算的一个偏移 |
关闭文件句柄
CloseHandle() 关闭文件句柄
CloseHandle包括文件、文件映射、进程、线程、安全和同步对象等。涉及文件处理时,这个函数通常与vb的close命令相似。应尽可能的使用close,因为它支持vb的差错控制。
//关闭一个内核对象
BOOL CloseHandle(HANDLE hObject); //Object代表一个已打开对象handle。
返回值
TRUE:执行成功;
FALSE:执行失败,可以调用GetLastError()获知失败原因。
关闭一个内核对象。其中包括文件、文件映射、进程、线程、安全和同步对象等。在CreateThread成功之后会返回一个hThread的handle,且内核对象的计数加1,CloseHandle之后,引用计数减1,当变为0时,系统删除内核对象。
若在线程执行完之后,没有调用CloseHandle,在进程执行期间,将会造成内核对象的泄露,相当于句柄泄露,但不同于内存泄露,这势必会对系统的效率带来一定程度上的负面影响。但当进程结束退出后,系统会自动清理这些资源。
win32 实现文件操作
方法如下
- 定义用于文件操作的句柄
- 创建文件
- 读或者写文件
- 关闭文件句柄
代码演示
TCHAR strArr[1024] = {};
//WndProc消息处理函数中
switch (message)
{
//鼠标的左键按下
case WM_LBUTTONDOWN:
{
//1.定义用于文件操作的句柄
HANDLE hFile = nullptr;
//2.创建文件
hFile = CreateFile(_T"1.txt", //路径的文件名,用相对路径
GENERIC_ALL, //文件访问权限,可读写
FILE_SHARE_READ, //共享只读读模式
nullptr; //安全属性
OPEN_ALWAYS; //文件创建方式
FILE_ATTRIBUTE_NORMAL,//文件属性
nullptr); //文件模板属性
//3.读或者写文件
char strp[1024] = "hello world 老师好";
DWORD len = 0;
//读文件
ReadFile(hFile,strp,1023,&len,nullptr);
//写文件
WriteFile(hFile, //操作文件的句柄
strp, //写入的内容
strlen(strp),//想写入的字符个数
&len, //写入的具体个数(输出)
nullptr);
Message(0,strArr,0,0);
//设置文件内部指针的偏移
SetFilePointer(hFile, //操作文件的句柄
0, //低32位偏移量
0, //高32位偏移量
FILE_BEGIN); //从文件的起始位置进行偏移
//4.关闭文件句柄
CloseHandle(hFile);
}
break;
}
文件的目录操作
FindFirstFile()
根据文件名查找文件
该函数到一个文件夹(包括子文件夹)去搜索指定文件 如果要使用附加属性去搜索文件的话 可以使用FindFirstFileEx函数。
//根据文件名查找文件
HANDLE FindFirstFile(LPCTSTR lpFileName, //lpFileName文件名(包括路径)
LPWIN32_FIND_DATA lpFindFileData);//指向一个用于保存文件信息的结构体
参数 类型及说明
lpFileName,String;类型欲搜索的文件名。参数可如下
"c:/Windows/*.*" //在c:\Windows目录中查找所有件
"c:/Windows/System32/*.dll"//在c:\Windows\System32目录中查找所有dll文件
"c:/Windows/System.ini" //在c:\Windows目录中查找System.ini文件
"c:/Windows/a???.*" //在c:\Windows目录中查找所有以a开头的文件名长度.为4个字符的文件
"Test.dat" //在当前目录查找Test.dat文件
"*.*" //在当前目录查找所有文件
(注!一定要带文件名。如果参数为“c:\Windows”,则返回的文件名为“Windows”,并且接下来调用FindNextFile会返回失败)
lpFindFileData WIN32_FIND_DATA类型结构体,这个结构用于装载与找到的文件有关的信息。该结构可用于后续的搜索
typedef struct _WIN32_FIND_DATA {
DWORD dwFileAttributes; // 文件属性
FILETIME ftCreationTime; // 文件创建时间
FILETIME ftLastAccessTime; // 文件最后一次访问时间
FILETIME ftLastWriteTime; // 文件最后一次修改时间
DWORD nFileSizeHigh; // 文件长度高32位
DWORD nFileSizeLow; // 文件长度低32位
DWORD dwReserved0; // 系统保留
DWORD dwReserved1; // 系统保留
TCHAR cFileName[MAX_PATH]; // 长文件名
TCHAR cAlternateFileName[14]; // 8.3格式文件名
} WIN32_FIND_DATA, *PWIN32_FIND_DATA;
其中 dwFileAttributes字段可以是下面取值的组合,通过这个字段可以检查找到的究竟是一个文件还是一个子目录,以及其他的文件属性:
值 | 描述 |
---|---|
FILE_ATTRIBUTE_ARCHIVE | 文件包含归档属性 |
FILE_ATTRIBUTE_COMPRESSED | 文件和目录被压缩 |
FILE_ATTRIBUTE_DIRECTORY | 找到的是一个目录 |
FILE_ATTRIBUTE_HIDDEN | 文件包含隐含属性 |
FILE_ATTRIBUTE_NORMAL | 文件没有其他属性 |
FILE_ATTRIBUTE_READONLY | 文件包含只读属性 |
FILE_ATTRIBUTE_SYSTEM | 文件包含系统属性 |
FILE_ATTRIBUTE_TEMPORARY | 文件是一个临时文件 |
返回的文件名中会包含".“和”…"。“.'代表本目录,"…"代表上一层目录。一般情况下需要把这两个名称过滤掉。比如要进行文件删除操作。
由这个函数返回的句柄可以作为一个参数用于FindNextFile函数。这样一来,就可以方便的枚举出与lpFileName参数指定的文件名相符的所有文件
FindNextFile()
可以用来遍历目录或文件时,判断当前目录下是否有下一个目录或文件。
//遍历目录或文件时,判断当前目录下是否有下一个目录或文件。
BOOL FindNextFile(HANDLE hFindFile, //上一次查找返回的文件句柄
LPWIN32_FIND_DATA lpFindFileData);// WIN32_FIND_DATA结构体,这个结构用于装载与找到的文件有关的信息。该结构可用于后续的搜索
此函数用于遍历目录或文件时,判断当前目录下是否有下一个目录或文件
Long,如执行成功,返回TRUE。否则为FALSE。
WIN32_FIND_DATA结构体详见上面的说明。
代码演示
TCHAR strArr[1024] = {};
//WndProc消息处理函数中
switch (message)
{
//鼠标的左键按下
case WM_LBUTTONDOWN:
{
//准备一个辅助数组
char fileStr[1024] = {};
//1.定义用于文件操作的句柄
HANDLE hFile = nullptr;
//2.创建文件
hFile = CreateFile(_T"2.txt", //路径的文件名,用相对路径
GENERIC_WRITE, //文件访问权限,只写
FILE_SHARE_READ, //共享只读读模式
nullptr; //安全属性
CREATE_ALWAYS; //文件创建方式
FILE_ATTRIBUTE_NORMAL,//文件属性
nullptr); //文件模板属性
//文件的数据结构
WIN32_FIND_DATAA fileData;
//查找第一个文件
HANDLE findFile = nullptr;
findFile = FindFirstFileA('Debug/*.*', //路径文件名,表示找Debug下的所有文件
&fileData);//文件数据结构
//情空保存文件名的辅助数组
memcpy(fileStr,fileData.cFileName,sizeof(char)*strlen(fileData.cFileName));
//文件名尾部拼接\r\n 表示换行
strcat(fileStr,"\r\n");
DWORD len = 0;
//把找到的文件名写入2.txt文件中
WriteFile(hFile,fileStr,strlen(fileStr),$len,nullptr);
//继续查找下一个文件
while(FindNextFileA(findFile,&fileData))
{
ZeroMemory(fileStr,sizeof(char)*1024);
memcpy(fileStr,fileData.cFileName,sizeof(char)*strlen(fileData.cFileName));
strcat(fileStr,"\r\n");
WriteFile(hFile,fileStr,strlen(fileStr),$len,nullptr);
}
//4.关闭文件句柄
CloseHandle(findFile);
CloseHandle(hFile);
}
break;
}