windows32 api文件操作

                                              本文有大量链接引用.如触犯了您的利益请下方留言

前言

熟悉的文件打开操作有open、fopen、createfile、CFile类

他们的关系(论坛上出现过的问题):CFile 或者 C++的fstrem或者C lib fopen,终究都会调用Win32 APICreateFile

CreateFile是操作系统提供的,Open由C++提供,内部也是调用CreateFile;他们在功能上没有什么区别;

windows中open依赖于CreateFile,但两者的返回值不是同一个东西,open返回的是一个数组的索引,CreateFile返回值是句柄表的多级索引

fopen与CreateFile比较(网文):

在 win7 x64 下,即使把 ACL 关闭,对一个肯定存在的文件(用 _access 检查也是存在),用 CreateFile 打开时,无论采用什么参数,都返回无效句柄 INVALID_HANDLE_VALUE。用 GetLastError 得到的错误竟然是:文件不存在,或者路径不存在!这应该是与 ACL 相关的一个问题,google了很久,也只是发现有人提出这个问题,但都没有解决该问题。无奈之下,只好抛弃微软,重用标准库的 fopen。因为标准库的 fopen 不会做 os 做的安全相关事情,所以轻松打开了文件。 同样,在写文件时,CreateFile 依然无奈,fopen轻松胜任。 随着 Android、iOS 越来越流行,代码的跨平台性就要求越高。对安全性要求不高的应用程序,弃用平台相关的 API,改用平台无关的标准库,显然是个明智之举。

但是在windows32环境下做开发,对于windows提供的api还是有必要了解的

windows api文件手册函数:点击打开链接 点击打开链接

正文

由于本人对文件操作仅限于创建、读、写等基础操作,这里仅给出基础api

一、创建、打开文件createfile   (createfile的详细信息点击打开链接)

HANDLE CreateFile(  

LPCSTR lpFileName,   //指向文件名的指针或filename对象路径名(LPCSTR的详细解释 点击打开链接)

DWORD dwDesiredAccess,   //访问模式 (DWORD 的详细解释点击打开链接)

DWORD dwShareMode,   //共享模式 (关于共享模式:点击打开链接)

LPSECURITY_ATTRIBUTES lpSecurityAttributes,   //指向安全属性的指针

DWORD dwCreationDisposition,   //创建方式

DWORD dwFlagsAndAttributes,   //文件属性

HANDLE hTemplateFile //用于复制文件句柄 (关于该参数点击打开链接)

);

lpFileName 文件名或路径

dwDesiredAccess 访问模式

0 不希望从设备读取数据或向设备写入数据。如果只想改变设备的配置(如:修改文件的时间戳),可以传0

GENERIC_READ 允许对设备进行只读访问

GENERIC_WRITE 允许对设备进行只写访问,该选项并没有隐含 GENERIC_READ标志

dwShareMode 共享模式

0                      要求独占对设备的访问。如果设备已经打开,CreateFile 调用会失败;如果成功地打开了设备,后续的 CreateFile 调用会失败

FILE_SHARE_READ 如果有其他对象要用该设备,我们要求它们不得修改设备的数据;如果设备已经以写入方式或独占方式打开,那么CreateFile调用会失败
FILE_SHARE_WRITE 如果有其他内核对象要使用该设备,则要求它们不得读取设备的数据
FILE_SHARE_DELETE 当对文件进行操作的时候,我们不关心文件是否被逻辑删除或移动。在Windows内部,系统会先将文件标记为待删除,然后当该文件所有已打开的句柄都被关闭的时候,再将其真正的删除

lpSecurityAttributes 指向安全属性的指针

指向一个SECURITY_ATTRIBUTES结构指针,定义了文件安全特性

dwCreationDisposition 创建方式

CREATE_NEW 创建一个新文件,如果同名文件已经存在,那么 CreateFile调用会失败
CREATE_ALWAYS 无论同名是否存在都创建新文件,若文件存在,则覆盖
OPEN_EXISTING 打开一个已有的文件或设备,如果文件或设备不存在,那么CreateFile调用会失败
OPEN_ALWAYS 打开一个已有的文件,如果文件存在,那么CreateFile会直接打开文件,如果不存在,则会创建一个新文件
TRUNCATE_EXISTING 打开一个已有的文件并将文件大小截断为0字节,如果文件不存在,那么CreateFile调用会失败

dwFlagsAndAttributes 文件属性

通信标志–缓存
FILE_FLAG_NO_BUFFERING 该标志表示在访问文件的时候不要使用任何数据缓存
FILE_FLAG_SEQUENTIAL_SCAN 指定系统顺序地访问文件,系统从文件读取的数据量会超过我们的要求(减少硬盘访问),指定了FILE_FLAG_NO_BUFFERING标志,该标志不生效
FILE_FLAG_RANDOM_ACCESS 该标志表示系统不要提前读取文件数据(指定FILE_FLAG_NO_BUFFERING,则该标志不生效)
FILE_FLAG_WRITE_THROUGH 禁止写入文件时,将数据缓存在内存中(减少数据丢失的可能性)
通信标志–其他标志
FILE_FLAG_DELETE_ON_CLOSE 文件所有的句柄都被关闭后,删除该文件
FILE_FLAG_BACKUP_SEMANTICS 用于备份和恢复软件。在打开或创建任何文件之前,为了确保视图打开文件或创建文件的进程具有所需的访问特权
FILE_FLAG_POSIX_SEMANTICS 让CreateFile在创建文件或打开文件时,以区分大小写的方式来查找文件名
FILE_FLAG_OPEN_REPARSE_POINT 告诉系统忽略文件的重解析属性(重解析属性允许一个文件系统过滤器对打开文件、读取文件、写入文件以及关闭文件这些行为进行修改)
FILE_FLAG_OPEN_NO_RECALL 该标志告诉系统不要将文件内容刚从脱机存储器(offline storage,比如磁带)恢复到联机存储器(即online storage, 如硬盘)
FILE_FLAG_OVERLAPPED 该标志告诉系统我们想以异步方式来访问设备
文件设置
FILE_ATTRIBUTE_ARCHIVE 应用程序用该标志来将文件标记为待备份或待删除。当CreateFile创建一个新文件时,会自动设置该标志
FILE_ATTRIBUTE_ENCRYPTED 文件是经过加密的
FILE_ATTRIBUTE_HIDDEN 文件是隐藏的。它不会出现在通常的目录清单中
FILE_ATTRIBUTE_NORMAL 文件没有其他属性。只有单独使用的时候,这个标志才有效(默认属性)
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 内容索引服务(content indexing service)不会对文件进行索引
FILE_ATTRIBUTE_OFFLINE 文件虽然存在,但文件内容已经被转移到脱机存储中
FILE_ATTRIBUTE_READONLY 文件只读
FILE_ATTRIBUTE_SYSTEM 文件是操作系统的一部分,专供操作系统使用

FILE_ATTRIBUTE_TEMPORARY 文件数据只会使用一小段时间。为了将访问时间降至最低,会尽量将文件数据保存在内存中

一般创建文件只要设置 FILE_ATTRIBUTE_NORMAL(默认属性)

hTemplateFile 用于复制文件句柄

指向用于存储的文件句柄,!=0则指定一个文件句柄,新的文件将从这个文件中复制扩展属性,如果该函数调用成功,返回文件句柄,否则返回INVALID_HANDLE_VALUE

调用示例

以只读方式打开已存在的文件

HANDLE hFILE = createfile("First.cpp",GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FLIE_ATTRIBUTE_NORMAL,NULL);

以只写方式打开已存在文件

HANDLE hFILE = createfile("First.cpp",GENERIC_WRITE,FILE_SHARE_READ,NULL,OPEN_EXISTING,FLIE_ATTRIBUTE_NORMAL,NULL);

创建一个新文件

HANDLE hFILE = createfile("First.cpp",GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FLIE_ATTRIBUTE_NORMAL,NULL);

*********************************************************************************************************************

二、向文件中写数据writefile   点击打开链接

bool writefile(

①HANDLE hFile,                                                     //文件句柄

②LPCVOID IPBuffer,                                              //数据缓存区指针(LPCVOID 点击打开链接)

③DWORD nNumberofBytesWritten,                     //你要写的字节数

④LPDWORD IpNumberofBytesWritten,              //用于保存实际写入的字节数(LPDWORD 点击打开链接)

⑤LPOVERLAPPED IpOverlapped                      //OVERLAPPED结构体指针(一般用NULL)

)

用法示例

向打开文件中写入一句话

char buffer[] = {"//hello my first file!!!"};

DWORD writelength;

booi write_ret = wirtefile(hFile,&buffer,strlen(buffer),&writelength,NULL);

三、设置文件指针setfilepointer点击打开链接

在对打开的文件进行操作时需要知道当前文件指针位置,是在文件开头还是文件末尾还是在哪里,打开文件时文件指针默认在文件开头,如果不设置文件指针的话,下次写入文件内容就会覆盖掉前面的内

DWORD WINAPI SetFilePointer(
①HANDLE     hFile,                                        //文件句柄
②LONG         lDistanceToMove,                     //32位有符号long型,表示要移动的位置(正数表示向后,负数表示向前)
③PLONG       lpDistanceToMoveHigh,           //
④DWORD     dwMoveMethod                       //移动模式

);

④dwMoveMethod   移动模式

一共有三种移动模式

FILE_BEGIN     从文件开始位置定位(此时参数②不能为负)

FILE_CURRENT  从文件当前位置向前或向后移动指针(比如写了一句话之后发现写错了,可以将指针移动至写之前的位置,再次写入)

FILE_END   从文件的末尾向前或向后定位指针

返回值:当前所处位置距文件开头的字符数,可以借此查看当前文件有多大

例:将文件指针设置到文件尾部

DWORD pLocation_len = setfilepointer(hFile,0,NULL,FILE_END);

四、判断文件长度GetFileSize点击打开链接

DWORD GetFileSize(

HANDLE hFile,                                 //文件句柄

LPDWORD LPFileSizeHigh               //指向高阶双字的文件大小的指针(此参数一般为NULL)

);

返回值:返回文件的大小

例:查看已打开文件的长度

DWORD filesize= GetFileSize(hFile,NULL);

五、从文件中读取数据ReadFile点击打开链接

BOOL ReadFile(
HANDLE hFile,                               //文件的句柄
LPVOID lpBuffer,                           //用于保存读入数据的一个缓冲区
DWORD nNumberOfBytesToRead, //要读入的字符数
LPDWORD lpNumberOfBytesRead, //指向实际读取字节数的指针
LPOVERLAPPED lpOverlapped       //如文件打开时指定了FILE_FLAG_OVERLAPPED,那么必须,用这个参数引用一个特殊的结构。该结构定义了一次异步读取操作。否则,应将这个参数设为NULL

  );

例:从已打开文件中读取数据

//获取文件大小
int file_length1 = GetFileSize(hFile,NULL);
cout << "文件大小为" << file_length1 << endl;
//从文件中读数据
    char * pbuffer11 = (char*)malloc(file_length1 + 1);  //创建缓冲区存放读取的内容
DWORD rel_read_len1 = 0;
bool read_ret = ReadFile(hFile,pbuffer11,file_length1,&rel_read_len1,NULL);
{
if(read_ret == 0)
cout << "read file error" << endl;
}
    pbuffer11[file_length1] = '\0';
cout << "读到文件全部内容:" << pbuffer11 << endl;
cout << "实际读到的长度" << rel_read_len1 << endl;
    free(pbuffer11);
//关闭文件流句柄

CloseHandle(hFile);

六、删除文件DeleteFile

Bool DeleteFile(

LPCSTR        lpFileName//要删除的文件名的指针

);

关于删除路径出错问题点击打开链接

例:删除文件

DeleteFile(_T("first.cpp"));

***************************************************************************************************

下面给出具体例子及运行结果

#include <Windows.h>
#include <iostream>
#include <tchar.h>

using namespace std;

int main()
{

	//创建一个新文件
	HANDLE hfile = CreateFile(_T("first.cpp"),GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
    if(hfile == INVALID_HANDLE_VALUE)
	{
		cout << "创建文件失败" << endl;
	}
	else
	{
        cout << "first.cpp创建成功" << endl;
	}

	//// 以只写方式打开已存在的文件
 //   HANDLE hfile = CreateFile(_T("first.cpp"),GENERIC_WRITE,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
	//if(INVALID_HANDLE_VALUE == hfile)
	//{
	//	cout << "open file error" << endl;
	//}

    DWORD plocation_len;
	//设置文件指针(打开文件时文件指针默认处于文件开头位置,如果要往里面写数据则需要设置文件指针位置)
	plocation_len = SetFilePointer(hfile,0,NULL,FILE_END);
	cout << "文件开头距文件指针字节数:" << plocation_len << endl;


	//向文件中写入数据
	char buffer[] = {"//hello my first create file!!!"};  //创建buffer里面存放要写的内容
	DWORD writelength;                                    //创建writelength,里面存放实际写入的长度,可以打印出来
	bool write_ret = WriteFile(hfile,&buffer,(DWORD)strlen(buffer),&writelength,NULL);
	if(write_ret == 0)
	{
		cout << " write file fault" << endl;
	}
	cout << "实际写入长度 " << writelength << endl; 
	cout << "action over" << endl;
    
	//设置文件指针
    plocation_len = SetFilePointer(hfile,0,NULL,FILE_END);
	cout << "文件开头距文件指针字节数:" << plocation_len << endl;
    
	//向文件中写入数据
    char buffer1[] = {"//ni hao zhong guo!"};
	DWORD writelength1;                                    //创建writelength,里面存放实际写入的长度,可以打印出来
	bool write_ret1 = WriteFile(hfile,&buffer1,(DWORD)strlen(buffer1),&writelength1,NULL);
	if(write_ret1 == 0)
	{
		cout << " write file fault" << endl;
	}
	cout << "实际写入长度 " << writelength1 << endl; 
	cout << "action1 over" << endl;

    CloseHandle(hfile);

	////设置文件指针(将文件指针设置到文件头)
	//plocation_len = SetFilePointer(hfile,0,NULL,FILE_BEGIN);
	//cout << "文件开头距文件指针字节数:" << plocation_len << endl;
   
	HANDLE hFile = CreateFile(_T("first.cpp"),GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
	if(INVALID_HANDLE_VALUE == hFile)
	{
		cout << "open file error" << endl;
	}

	//获取文件大小
	int file_length1 = GetFileSize(hFile,NULL);
	cout << "文件大小为" << file_length1 << endl;

	//从文件中读数据
    char * pbuffer11 = (char*)malloc(file_length1 + 1);  //创建缓冲区存放读取的内容
	DWORD rel_read_len1 = 0;
	bool read_ret = ReadFile(hFile,pbuffer11,file_length1,&rel_read_len1,NULL);
	{
		if(read_ret == 0)
		cout << "read file error" << endl;
	}
    pbuffer11[file_length1] = '\0';
	cout << "读到文件全部内容:" << pbuffer11 << endl;
	cout << "实际读到的长度" << rel_read_len1 << endl;
    free(pbuffer11);
	//关闭文件流句柄
	CloseHandle(hFile);

	if(DeleteFile(_T("first.cpp")))
	{
		cout << "first.cpp被删除" << endl;
	}

     
	return 0;
}
运行结果




保持更新(后续如用到其他函数会更新本博客)


猜你喜欢

转载自blog.csdn.net/qq_37059136/article/details/80935967
今日推荐