[WinAPI] API 10 [创建、打开、读写文件,获取文件大小]

 

 

在Windows系统中,创建和打开文件都是使用API函数CreateFile,CreateFile通过指定不同的参数来表示是新建一个文件,打开已经存在的文件,还是重新建立文件等。读写文件最为直接的方式是使用ReadFile和WriteFile函数,也可以使用文件镜像,获取文件大小一般使用GetFileSize函数,也可以使用GetFileAttributesEx等函数(在上节介绍)。读写文件、获取文件大小之前都需要使用CreateFile创建或打开的文件,获得文件句柄。
在文件操作中,文件句柄是一个关键的概念。文件句柄惟一标识了一个文件,ReadFile、WriteFile、GetFileSize等函数是使用文件句柄作为参数来表示,用户需要读、写、获取大小的文件是哪一个文件。在对文件进行操作前,都必须要使用CreateFile获得文件句柄。

 

(1)CreateFile
CreateFile是文件操作中最主要的一个函数。几乎所有的文件操作都需要使用到文件句柄。而CreateFile函数为这些操作建立文件句柄。CreateFile函数的参数多,而且比较复杂,涉及文件名、文件的共享模式、存取方式、操作模式、权限、标志和文件属性等。每一个参数都可以有多种值可供选择,代表了不同的意义。

◇参数
lpFileName:输入参数,操作对象文件的相对路径或绝对路径。
dwDesiredAccess:输入参数,指明对文件对象的操作存取方式,可以是GENERIC_READ,表示需要读文件;可以是GENERIC_WRITE,表示需要写文件;也可以是GENERIC_READGENERIC_WRITE,表示既可以读也可以写。
dwShareMode:输入参数,共享模式。指明与其他进程是否共享该文件,可以是共享读(FILE_SHARE DELETE)、共享写(FILE_SHARE_WRITE)、共享删除(FILE_SHARE.READ),如果要指明多个属性,使用“位与~‘I”运算。如果指明上述参数,其他进程就可以对文件进行相关操作。如果本进程需要独占本文件,则将本参数设置为0。
lpSecurityAttributes:指向SECURITY_ATTRIBUTES结构的指针,表示本文件句柄的安全属性,能影响其是否可被子进程继承等操作。如果设定为NULL,则子进程不可继承本句柄。SECURITY ATTRIBUTES结构不常用,对此数据结构的设置,涉及Windows系统中对权限管理的原理,在本章中不作详细说明。
dwCreationDisposition:输入参数,操作模式。

dwFlagsAndAttributes:输入参数,文件属性和文件标志

一般情况下文件属性较常用,而操作标志不常用,可以使用“1”运算符指定多个属性和标志。
hTemplateFile:输入参数,当存取权限包括GENERIC_WRITE时,可以设置为一个模板文件的句柄。一般情况下,可设置为NULL,表示不使用模板文件。
◇返回值
返回HANDLE数据类型值,表示文件的句柄,如果返回INVALID_HANDLE_VALUE,表示操作失败。

 

(2)ReadFile。
ReadFile动能是从文件中读出数据。需要使用CreateFile所返回的文件句柄。

◇参数
hFile:输入参数,读取数据的文件对象,由CreateFile创建,调用CreateFile打开文件时需要指明GENERIC_READ读取操作模式。
lpBuffer:输入参数,指向读取文件数据存储的内存缓冲区。
nNumberOfBytesToRead:输入参数,指明需要从文件中读出的数据的大小,不能大于lpBuffer内存块的大小,否则会造成溢出。
lpNumberOfBytesRead:输出参数,指向存储实际读出的数据大小的DWORD变量。在读文件时,可能由于已经到达文件尾等原因,其值可能小于rtNumberOfBytesToRead。如果lpOverlapped为NULL,则该参数不能为NULL。
lpOverlapped:输入参数,指向OVERLAPPED结构体的指针,如果调用CreateFile时设置了FILE_FLAG_OVERLAPPED标志,则需要使用该参数,否则可以为NULL。
◇返回值
返回BOOL值,表示读文件是否成功。
◇使用说明
在读的过程中,文件指针会随着读操作的进行而自动移动,在循环调用本函数时,会顺序读出文件的内容,如果程序返回失败,可以使用GetLastError函数获取错误信息。

 

(3)WriteFile。
WriteFile函数的功能是将数据写入到文件中,写入到文件指针所在的位置,写入操作完成后,文件指针会移动到写入的数据之后

◇参数
hFile:输入参数,写入数据的文件对象,由CreateFile创建,调用CreateFile打开文件时,需要指明GENERIC_WRITE读取操作模式。
lpBuffer:输入参数,指向需写入文件数据存储的内存缓冲区。
nNumberOBytesToWrite:输入参数,指明需要写入文件中的数据的大小。
lpNumberOiBytesWritten:输出参数,指向存储真实写入的数据大小的变量,可能由于已经到达文件尾等原因,其值可能与nNumberOfBytesToWrite不同。如果lpOverlapped为NULL,则该参数不能为NULL。
lpOverlapped:输入参数,指向OVERLAPPED结构体的指针,如果调用CreateFile时设置了FILE_FLAG_OVERIAPPED标志,则需要使用该参数。可以为NULL。
◇返回值
返回BOOL值,表示写文件是否成功。
◇使用说明

在读的过程中,文件指针会随着写操作的进行而移动,在循环调用本函数时,会按顺序写入文件内容。如果程序返回失败,可以使用 GetLastError函数获取错误信息。

 

(4)GetFileSize、GetFileSizeEX.
GetFileSize、GetFileSizeEX的功能是一致的,都是获取文件大小

◇参数
GetFileSize的参数如下。
hFile:输入参数,读取数据的文件对象,由CreateFile创建,调用CreateFile打开文件时需要指明GENERIC_READ读取操作模式或者GENERIC_WRITE写入操作模式。
lpFileSizeHigh:输出参数,表示得到的文件大小的高32位。该参数可以为NULL,为NULL时表示文件大小可以用DWORD表示。具体解释请参考返回值部分。
GetFileSizeEx的参数如下。
hFile:输入参数,读取数据的文件对象,由CreateFile创建,调用CreateFile打开文件时,需要指明GENERIC_READ读取操作模式或者GENERIC_WRITE写入操作模式。
lpFileSize:输出参数,指向储存文件大小的一个LARGE_ INTEGER联合体,前面已经介绍过了LARGE.1NTEGER结构的相关内容,参见API 9 小节关键数据结构部分。
◇返回值
GetFileSize成功时,返回值为一个表示文件大小DWORD值。
GetFileSize失败时,如果lpFileSizeHigh为NULL,返回INVALID_ FILE_SIZE并可以调用GetLastError函数获取更详细的错误信息;如果lpFileSizeHigh为非NULL,那么同样返回INVALID_FILE_SIZE并且尝试读取lpFileSizeHigh指向的值放在高32位,并将其和返回的低32位DWORD连起来成为一个64位的值来表示文件大小。lpFileSizeHigh为合法值则GetLastError返回NO_ERROR,表示该API仍然成功;否则,GetLastError返回一个不等于NO_ERROR的值。

GetFileSizeEx直接返回BOOL值,表示读文件是否成功。

◇使用说明
实际上这两个函数的区别就在于,对文件大小超出DWORD的情况采取不同处理方式。由于历史原因,GetFileSize用两个32位值来分别储存64位文件大小的高位和地位;而GetFileSizeEx直接将文件大小储存在64位的联合体中。

 

>>>本实例使用CreateFile、ReadFile、WriteFile来完成创建、打开、读写文件的功能。笔者在实例中自己编写一个SaveDataToFile函数在D盘根目录下建立一个show.txt并向文件中写入数据,并编写了一个ReadFileContent函数读取文件的内容。

 

 

  1 #include <Windows.h>
  2 #include <stdio.h>
  3 
  4 DWORD ReadFileContent(LPSTR szFilePath)
  5 {
  6     //文件大小
  7     HANDLE hFileRead;
  8     //保存文件大小
  9     LARGE_INTEGER liFileSize;
 10     //成功读取的文件数据大小
 11     DWORD dwReadedSize;
 12     //累加计算已经读取的数据的大小
 13     LONGLONG liTotalRead=0;
 14     //文件数据缓存
 15     BYTE lpFileDataBuffer[32];
 16 
 17     //打开已经存在的文件,读取内容
 18     hFileRead = CreateFileA(szFilePath,//name
 19         GENERIC_READ,                   //以读方式打开
 20         FILE_SHARE_READ,               //可共享读
 21         NULL,                           //默认安全设置
 22         OPEN_EXISTING,                   //只打开已经存在的文件
 23         FILE_ATTRIBUTE_NORMAL,           //常规文件属性
 24         NULL);                           //无模板
 25     //打开文件是否成功
 26     if(hFileRead==INVALID_HANDLE_VALUE)
 27     {
 28         printf("打开文件失败: %d",GetLastError());
 29     }
 30     if(!GetFileSizeEx(hFileRead,&liFileSize))
 31     {
 32         printf("获取文件大小失败: %d",GetLastError());
 33     }
 34     else
 35     {
 36         printf("文件大小为: %d\n",liFileSize.QuadPart);
 37     }
 38     //循环读取并打印内容
 39     while(TRUE)
 40     {
 41         DWORD i;
 42         if(!ReadFile(hFileRead,//读取文件句柄
 43             lpFileDataBuffer,  //存储读取文件内容
 44             32,                   //读取的大小(字节)
 45             &dwReadedSize,       //实际读取的大小
 46             NULL))               //不使用Overlapped
 47         {
 48             printf("读取文件错误: %d\n",GetLastError());
 49             break;
 50         }
 51         printf("读取了%d字节,文件内容是: ",dwReadedSize);
 52 
 53         for(i=0;i<dwReadedSize;i++)
 54         {
 55             printf("0x%x ",lpFileDataBuffer[i]);
 56         }
 57         printf("\n");
 58         liTotalRead+=dwReadedSize;
 59         if(liTotalRead==liFileSize.QuadPart)
 60         {
 61             printf("读取文件结束\n");
 62             break;
 63         }
 64     }
 65     CloseHandle(hFileRead);
 66     return 0;
 67 }
 68 
 69 DWORD SaveDataToFile(
 70     LPSTR szFilePath,
 71     LPVOID lpData,
 72     DWORD dwDataSize)
 73 {
 74     //文件句柄
 75     HANDLE hFileWrite;
 76     //成功写入的数据大小
 77     DWORD dwWritedDateSize;
 78     //打开已经存在的文件,读取内容
 79     hFileWrite=CreateFileA(szFilePath,//要打开的文件名
 80         GENERIC_WRITE,//以写方式打开开
 81         0,//可共享读
 82         NULL,//默认安全设置
 83         OPEN_ALWAYS,//打开已经存在的文件
 84         FILE_ATTRIBUTE_NORMAL,//常规属性打开
 85         NULL);//无模板
 86     //判断是否成功打开
 87     if(hFileWrite==INVALID_HANDLE_VALUE)
 88     {
 89         printf("打开文件失败: %d\n",GetLastError());
 90     }
 91     //设置文件指针到文件为
 92     SetFilePointer(hFileWrite,0,0,FILE_END);
 93     //将数据写入文件
 94     if(!WriteFile(hFileWrite,lpData,dwDataSize,&dwWritedDateSize,NULL))
 95     {
 96         printf("写文件失败: %d\n",GetLastError());
 97     }
 98     else
 99     {
100         printf("写文件成功,写入%d字节。\n",dwWritedDateSize);
101     }
102     CloseHandle(hFileWrite);
103     return 0;
104 }
105 int main()
106 {
107     LPSTR szFileData="这是一个例子";
108     SaveDataToFile("D:\\show.txt",szFileData,lstrlenA(szFileData));
109     ReadFileContent("D:\\show.txt");
110     return 0;
111 }

 

posted @ 2014-03-11 00:36  beautifulzzzz  阅读(6871)  评论(0编辑  收藏  举报