C语言readfile函数如何正确使用?

99ANYc3cd6
预计阅读时长 23 分钟
位置: 首页 C语言 正文

在标准的 C 语言库(C Standard Library)中,并没有一个叫做 readfile 的函数。

c语言readfile用法
(图片来源网络,侵删)

你可能在某些教程、特定平台(如 Windows)的文档,或者是其他语言(如 PHP)中看到过这个名字,在 C 语言中,与文件读取相关的核心函数是 fopen, fread, fgets, fgetc 等。

Windows API 提供了一个名为 ReadFile 的函数,它是一个底层的、更底层的文件操作函数,为了全面回答你的问题,我将分别讲解:

  1. 标准 C 语言中的文件读取方法(最常用、最可移植)
  2. Windows API 中的 ReadFile 函数(特定于 Windows 平台)

标准 C 语言中的文件读取方法 (推荐)

这是在所有支持 C 语言的平台上(Windows, Linux, macOS 等)都通用的方法,其核心思想是:打开文件 -> 读取数据 -> 关闭文件

主要步骤和函数:

  1. *`FILE fopen(const char filename, const char mode)`**

    c语言readfile用法
    (图片来源网络,侵删)
    • 作用:打开一个文件,并返回一个指向 FILE 结构体的指针,这个指针被称为“文件流指针”或“文件句柄”。
    • 参数
      • filename: 要打开的文件名(可以包含路径)。
      • mode: 文件打开模式。
        • "r": 只读,文件必须存在。
        • "w": 只写,如果文件存在,则清空内容;如果不存在,则创建新文件。
        • "a": 追加,在文件末尾写入,如果文件不存在,则创建新文件。
        • "r+": 读写,文件必须存在。
        • "w+": 读写,如果文件存在,则清空内容;如果不存在,则创建新文件。
        • "a+": 读写,在文件末尾写入和读取,如果文件不存在,则创建新文件。
    • 返回值:成功返回 FILE* 指针,失败返回 NULL使用前必须检查!
  2. size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)

    • 作用:从文件流中读取二进制数据
    • 参数
      • ptr: 指向一个内存缓冲区的指针,用于存放读取到的数据。
      • size: 每个数据项的大小(单位是字节)。
      • nmemb: 要读取的数据项的个数。
      • stream: 由 fopen 返回的文件流指针。
    • 返回值:成功返回实际读取到的数据项的个数,如果到达文件末尾或出错,可能返回 nmemb(表示成功读取了所有请求的数据),也可能返回一个小于 nmemb 的值(表示在读取过程中到达了文件末尾或发生错误)。
  3. *`char fgets(char str, int n, FILE stream)`**

    • 作用:从文件流中读取一行文本
    • 参数
      • str: 指向一个字符数组的指针,用于存放读取到的字符串。
      • n: 要读取的最大字符数(包括结尾的 \0)。
      • stream: 文件流指针。
    • 返回值:成功返回 str 指针,如果到达文件末尾或出错,返回 NULL
  4. *`int fclose(FILE stream)`**

    • 作用:关闭文件流,释放与文件相关的资源。
    • 返回值:成功返回 0,失败返回 EOF

示例代码

下面通过两个例子来展示如何使用这些函数。

c语言readfile用法
(图片来源网络,侵删)

示例 1:使用 fgets 逐行读取文本文件

假设我们有一个名为 test.txt 的文件,内容如下:

Hello, world!
This is the second line.
This is the third line.

代码:

#include <stdio.h>
#include <stdlib.h> // 用于 exit 函数
#define MAX_LINE_LENGTH 256
int main() {
    FILE *fp;
    char line[MAX_LINE_LENGTH];
    // 1. 打开文件
    fp = fopen("test.txt", "r");
    if (fp == NULL) {
        perror("Error opening file"); // perror 会打印出具体的错误信息
        return 1; // 返回非零表示错误
    }
    printf("File opened successfully. Reading lines:\n");
    // 2. 逐行读取文件
    // fgets 会读取一行,包括换行符 \n
    // fgets 返回 NULL,表示已经到达文件末尾或发生错误
    while (fgets(line, MAX_LINE_LENGTH, fp) != NULL) {
        printf("%s", line); // 直接打印读取到的一行
    }
    // 3. 关闭文件
    fclose(fp);
    printf("\nFile closed.\n");
    return 0;
}

示例 2:使用 fread 读取二进制文件

假设我们有一个名为 data.bin 的二进制文件,里面存储了一些整数。

代码:

#include <stdio.h>
#include <stdlib.h>
int main() {
    FILE *fp;
    int buffer[10]; // 假设文件里有 10 个整数
    int num_items_read;
    // 1. 以二进制模式打开文件
    fp = fopen("data.bin", "rb"); // "rb" 表示 "read binary"
    if (fp == NULL) {
        perror("Error opening binary file");
        return 1;
    }
    printf("Binary file opened successfully. Reading data...\n");
    // 2. 读取数据
    // sizeof(int) 是每个整数的大小
    // 10 是要读取的整数个数
    // 所以总共要读取 10 * sizeof(int) 字节的数据
    num_items_read = fread(buffer, sizeof(int), 10, fp);
    if (num_items_read < 10) {
        if (feof(fp)) {
            printf("Reached end of file. Only read %d items.\n", num_items_read);
        } else if (ferror(fp)) {
            perror("Error reading file");
        }
    } else {
        printf("Successfully read %d integers:\n", num_items_read);
        for (int i = 0; i < num_items_read; i++) {
            printf("buffer[%d] = %d\n", i, buffer[i]);
        }
    }
    // 3. 关闭文件
    fclose(fp);
    return 0;
}

Windows API 中的 ReadFile 函数

ReadFile 是 Windows 系统提供的更底层的 I/O 函数,它不依赖于 C 标准库的 FILE 结构,而是直接操作操作系统的“句柄”(Handle),它通常用于高性能或与 Windows 其他 API 交互的场景。

主要特点:

  • 句柄:它不使用 FILE*,而是使用 HANDLE 类型的句柄,句柄需要通过 CreateFile 函数来获取。
  • 同步/异步ReadFile 支持同步和异步操作。
  • 直接操作:它直接读写内存地址,不经过 C 标准库的缓冲区。

函数原型:

BOOL ReadFile(
  HANDLE       hFile,        // 文件句柄
  LPVOID       lpBuffer,     // 数据缓冲区
  DWORD        nNumberOfBytesToRead, // 要读取的字节数
  LPDWORD      lpNumberOfBytesRead, // 实际读取的字节数 (输出参数)
  LPOVERLAPPED lpOverlapped  // 用于异步操作 (通常为NULL)
);

示例代码

#include <windows.h>
#include <stdio.h>
int main() {
    HANDLE hFile;
    CHAR buffer[256];
    DWORD dwBytesRead; // 用于存储实际读取的字节数
    // 1. 使用 CreateFile 打开文件,获取句柄
    // GENERIC_READ 表示读取权限
    // OPEN_EXISTING 表示文件必须已存在
    // FILE_ATTRIBUTE_NORMAL 是普通文件属性
    // NULL 表示不使用模板文件
    hFile = CreateFile(
        "test.txt",                // 文件名
        GENERIC_READ,              // 访问模式 (只读)
        FILE_SHARE_READ,           // 共享模式 (允许其他进程读取)
        NULL,                      // 安全属性 (默认)
        OPEN_EXISTING,             // 创建模式 (文件必须存在)
        FILE_ATTRIBUTE_NORMAL,     // 文件属性
        NULL                       // 模板文件句柄
    );
    if (hFile == INVALID_HANDLE_VALUE) {
        printf("CreateFile failed (%d)\n", GetLastError());
        return 1;
    }
    printf("File opened with CreateFile. Reading content...\n");
    // 2. 使用 ReadFile 读取文件
    // buffer 是存放数据的缓冲区
    // sizeof(buffer) 是希望读取的最大字节数
    // &dwBytesRead 是一个指针,函数会在这里写入实际读取的字节数
    // NULL 表示同步操作
    if (ReadFile(hFile, buffer, sizeof(buffer), &dwBytesRead, NULL)) {
        // 读取成功
        if (dwBytesRead == 0) {
            printf("Reached end of file.\n");
        } else {
            // 确保字符串以 '\0' 
            buffer[dwBytesRead] = '\0';
            printf("Read %d bytes from file:\n%s", dwBytesRead, buffer);
        }
    } else {
        // 读取失败
        printf("ReadFile failed (%d)\n", GetLastError());
    }
    // 3. 使用 CloseHandle 关闭句柄
    CloseHandle(hFile);
    return 0;
}

总结与对比

特性 标准 C 库 (fopen/fread) Windows API (CreateFile/ReadFile)
可移植性 ,所有 C 语言平台都支持。 ,仅限 Windows 系统。
易用性 ,接口简单,有 fgets 等便捷函数。 ,需要手动管理句柄,错误处理更复杂。
底层性 较高,是 C 标准库封装了操作系统调用。 最高,直接调用系统内核函数。
性能 通常足够,标准库有自己的缓冲机制。 可能更高,尤其是在处理大量 I/O 或需要异步操作时。
适用场景 绝大多数情况,特别是文本文件处理、跨平台应用。 Windows 特定应用、驱动程序开发、需要精细控制 I/O 的场景。

给初学者的建议:

除非你有特殊的需求(例如编写纯 Windows 程序或需要极致性能),否则请优先使用标准 C 语言的文件 I/O 函数 (fopen, fread, fgets 等),它们更简单、更安全、更具可移植性。

-- 展开阅读全文 --
头像
页关键词如何调用?
« 上一篇 02-26
织梦自定义内容页模板
下一篇 » 02-26
取消
微信二维码
支付宝二维码

目录[+]