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

你可能在某些教程、特定平台(如 Windows)的文档,或者是其他语言(如 PHP)中看到过这个名字,在 C 语言中,与文件读取相关的核心函数是 fopen, fread, fgets, fgetc 等。
Windows API 提供了一个名为 ReadFile 的函数,它是一个底层的、更底层的文件操作函数,为了全面回答你的问题,我将分别讲解:
- 标准 C 语言中的文件读取方法(最常用、最可移植)
- Windows API 中的
ReadFile函数(特定于 Windows 平台)
标准 C 语言中的文件读取方法 (推荐)
这是在所有支持 C 语言的平台上(Windows, Linux, macOS 等)都通用的方法,其核心思想是:打开文件 -> 读取数据 -> 关闭文件。
主要步骤和函数:
-
*`FILE fopen(const char filename, const char mode)`**
(图片来源网络,侵删)- 作用:打开一个文件,并返回一个指向
FILE结构体的指针,这个指针被称为“文件流指针”或“文件句柄”。 - 参数:
filename: 要打开的文件名(可以包含路径)。mode: 文件打开模式。"r": 只读,文件必须存在。"w": 只写,如果文件存在,则清空内容;如果不存在,则创建新文件。"a": 追加,在文件末尾写入,如果文件不存在,则创建新文件。"r+": 读写,文件必须存在。"w+": 读写,如果文件存在,则清空内容;如果不存在,则创建新文件。"a+": 读写,在文件末尾写入和读取,如果文件不存在,则创建新文件。
- 返回值:成功返回
FILE*指针,失败返回NULL。使用前必须检查!
- 作用:打开一个文件,并返回一个指向
-
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)- 作用:从文件流中读取二进制数据。
- 参数:
ptr: 指向一个内存缓冲区的指针,用于存放读取到的数据。size: 每个数据项的大小(单位是字节)。nmemb: 要读取的数据项的个数。stream: 由fopen返回的文件流指针。
- 返回值:成功返回实际读取到的数据项的个数,如果到达文件末尾或出错,可能返回
nmemb(表示成功读取了所有请求的数据),也可能返回一个小于nmemb的值(表示在读取过程中到达了文件末尾或发生错误)。
-
*`char fgets(char str, int n, FILE stream)`**
- 作用:从文件流中读取一行文本。
- 参数:
str: 指向一个字符数组的指针,用于存放读取到的字符串。n: 要读取的最大字符数(包括结尾的\0)。stream: 文件流指针。
- 返回值:成功返回
str指针,如果到达文件末尾或出错,返回NULL。
-
*`int fclose(FILE stream)`**
- 作用:关闭文件流,释放与文件相关的资源。
- 返回值:成功返回
0,失败返回EOF。
示例代码
下面通过两个例子来展示如何使用这些函数。

示例 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 等),它们更简单、更安全、更具可移植性。
