C语言文件操作:CreateFile与fopen对比及示例

阿麦
阿麦
发布时间:2026-10-14 | 3人浏览过
原创

本文介绍了C语言中两种核心文件操作方式:使用Windows API的CreateFile进行底层句柄控制,以及使用C标准库的fopen进行流式数据读写。通过具体代码示例,详细解析了打开文件、写入缓冲区、同步缓存、重置指针及关闭资源的标准流程,帮助开发者根据性能需求选择合适方案。

Windows API方式:CreateFile底层操作

CreateFile是Windows系统中用于创建或打开文件的底层API,它返回一个文件句柄(HANDLE)。这种方式提供了更细粒度的控制,适合需要精确管理文件属性、权限或进行高性能IO的场景。以下是一个完整的操作流程,包括打开、获取大小、写入、同步、读取和关闭。

第1步:初始化头文件并定义主函数入口

首先包含必要的头文件。stdafx.h通常用于预编译头,windows.h提供Windows API支持。在控制台程序启动时,进入main函数。

#include "stdafx.h"
#include <windows.h>
#include <stdio.h>

void main(int argc, char* argv[])
{
    // ... 后续步骤
}

第2步:打开文件并验证句柄有效性

调用CreateFile打开指定路径的文件。参数说明如下:

  • lpFileName: 文件路径,如 C:\S.txt。
  • dwDesiredAccess: 访问权限,此处使用 GENERIC_READ|GENERIC_WRITE 同时支持读写。
  • dwShareMode: 共享模式,设为 0 表示独占访问。
  • lpSecurityAttributes: 安全属性,设为 NULL 使用默认设置。
  • dwCreationDisposition: 创建行为,此处使用 OPEN_EXISTING,要求文件必须存在。
  • dwFlagsAndAttributes: 文件属性,FILE_ATTRIBUTE_NORMAL 表示普通文件。
  • hTemplateFile: 模板文件句柄,设为 NULL。

操作完成后,必须检查返回值是否等于 INVALID_HANDLE_VALUE。若相等,则通过 GetLastError() 获取错误码并提示失败。

    HANDLE hDevice = CreateFile("C:\\S.txt",
        GENERIC_READ | GENERIC_WRITE,
        0,
        NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        NULL);

    if (hDevice == INVALID_HANDLE_VALUE)
    {
        printf("Failed to obtain file with %d error code !\n", GetLastError());
        return;
    }

第3步:获取文件大小(可选)

使用 GetFileSize 函数获取文件当前长度,单位为字节。第二个参数指向 DWORD 变量以接收高32位值,若只需低32位可传入 NULL。

    DWORD dwSize = GetFileSize(hDevice, NULL);
    printf("File size: %d bytes\n", dwSize);

第4步:准备缓冲区并执行写入操作

定义字符数组作为写入缓冲区。调用 WriteFile 将数据写入文件。注意:WriteFile 不会自动将数据刷入磁盘存储介质,需配合后续同步操作。

  • hFile: 文件句柄。
  • lpBuffer: 要写入的数据缓冲区。
  • nNumberOfBytesToWrite: 要写入的字节数。
  • lpNumberOfBytesWritten: 实际写入字节数的输出变量。
    char chBuffer[10] = "5469";
    DWORD dwWriteSize = 0;
    BOOL bRet = WriteFile(hDevice, chBuffer, 4, &dwWriteSize, NULL);
    
    if(bRet)
    {
        printf("Write success. Bytes written: %d\n", dwWriteSize);
    }
    else
    {
        printf("Write failed with error code: %d\n", GetLastError());
    }

第5步:同步文件缓冲区到磁盘

为了确保刚才写入的数据物理上保存到硬盘,避免系统崩溃或断电导致数据丢失,必须调用 FlushFileBuffers。这是一个耗时操作,但在关键数据存储时必不可少。

    FlushFileBuffers(hDevice); 

第6步:重置文件指针并执行读取

由于之前进行了写入,文件指针可能位于文件末尾。为了从头读取,使用 SetFilePointer 将指针移回文件开头(FILE_BEGIN)。

接着调用 ReadFile 从文件中读取数据到 chBuffer。注意读取缓冲区的大小应大于或等于预期读取的字节数。

    LONG lDistance = 0;
    // 将文件指针移动到文件开头
    DWORD dwPtr = SetFilePointer(hDevice, lDistance, NULL, FILE_BEGIN);
    
    DWORD dwReadSize = 0;
    // 重置缓冲区以防残留
    memset(chBuffer, 0, sizeof(chBuffer)); 
    
    bRet = ReadFile(hDevice, chBuffer, 10, &dwReadSize, NULL);
    
    if (bRet && dwReadSize > 0)
    {
        printf("Read content: %s\n", chBuffer);
    }
    else
    {
        printf("Read failed or no data.");
    }

第7步:关闭文件句柄

操作结束后,务必调用 CloseHandle 释放资源,否则会导致句柄泄露。

    CloseHandle(hDevice);
    return ;
}

C标准库方式:fopen流式文件操作

相比于CreateFile,C标准库提供的fopen更为简洁,适用于跨平台应用或不需要复杂文件属性的常规读写任务。它基于文件指针(FILE*)进行管理,抽象了底层的硬件交互。

第1步:声明文件指针并打开文件

使用FILE*类型声明指针。调用fopen打开文件,第一个参数为路径,第二个参数为模式字符串。常用模式包括"r"(只读)、"w"(只写,清空原文件)、"rb"(二进制只读)、"wb"(二进制只写)等。本例中使用"rb"以二进制模式打开,常用于处理非文本文件或确保兼容性。

    FILE *fp_sys;
    fp_sys = fopen("data.bin", "rb"); // 假设打开一个二进制文件
    
    if(fp_sys == NULL) {
        // 打开失败处理,可根据环境使用printf或日志记录
        fprintf(stderr, "Unable to open file\n");
        exit(1); 
    }

第2步:执行文件I/O操作

打开成功后,可使用fread、fwrite、fscanf等函数进行操作。例如,读取缓冲区数据:

    char datain[101];
    size_t items_read = fread(datain, 1, sizeof(datain), fp_sys);
    if(items_read > 0) {
        // 处理读取到的数据
        printf("Read %zu bytes\n", items_read);
    }

第3步:关闭文件

同样地,操作完成后需调用fclose释放关联的资源缓冲区并关闭文件描述符。

    fclose(fp_sys);

总结与建议

CreateFile适用于Windows环境下对文件系统有高精度控制需求的场景,如异步IO、内存映射文件或特殊权限管理;而fopen因其简单性和跨平台特性,更适合通用应用程序的快速开发。在实际工程中,应根据目标平台和性能要求选择合适的文件操作接口。 以上就是C语言文件操作方法CreateFile和fopen的详细内容,更多关于C++文件读写技巧的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表