• [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
    ",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
    ",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("
    ");
     58         liTotalRead+=dwReadedSize;
     59         if(liTotalRead==liFileSize.QuadPart)
     60         {
     61             printf("读取文件结束
    ");
     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
    ",GetLastError());
     90     }
     91     //设置文件指针到文件为
     92     SetFilePointer(hFileWrite,0,0,FILE_END);
     93     //将数据写入文件
     94     if(!WriteFile(hFileWrite,lpData,dwDataSize,&dwWritedDateSize,NULL))
     95     {
     96         printf("写文件失败: %d
    ",GetLastError());
     97     }
     98     else
     99     {
    100         printf("写文件成功,写入%d字节。
    ",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 }
  • 相关阅读:
    如何制作挖空的填空题试卷?
    原型制图工具有哪些?
    书籍推荐?来几本吧
    离线部署ELK+kafka日志管理系统【转】
    Elasticsearch5.0 安装问题集锦【转】
    在Nginx服务器上屏蔽IP
    MySQL Warning: Using a password on the command line interface can be insecure.解决办法
    不老的神器:安全扫描器Nmap渗透使用指南【转】
    MySQL数据库设置为只读及测试【转】
    Linux中切换用户变成-bash4.1-$的解决方法
  • 原文地址:https://www.cnblogs.com/zjutlitao/p/3593056.html
Copyright © 2020-2023  润新知