C 库函数– fread() 

在 C 语言中,fread() 是一个标准库函数,定义在 <stdio.h> 头文件中,用于从文件中读取数据。它常用于二进制或文本文件的读取操作,是处理文件输入的常用工具。以下是对 fread() 函数的详细中文讲解:


1. 函数概述

  • 定义fread() 从指定的文件流中读取指定数量的数据,并将其存储到内存中的缓冲区。
  • 函数原型
  size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
  • 参数
  • ptr:指向存储读取数据的内存缓冲区的指针(可以是数组或其他内存区域)。
  • size:每个数据块的字节大小(以字节为单位)。
  • nmemb:要读取的数据块数量。
  • stream:指向文件流的指针(通常通过 fopen() 打开)。
  • 返回值
  • 成功时,返回实际读取的数据块数量(size_t 类型,可能少于 nmemb)。
  • 如果发生错误或到达文件末尾(EOF),返回值可能小于 nmemb,甚至为 0。
  • 头文件<stdio.h>

2. 函数功能

  • fread() 按照指定的块大小(size)和块数量(nmemb)从文件中读取数据,总读取字节数为 size * nmemb
  • 读取的数据存储在 ptr 指向的内存中。
  • 常用于二进制文件读取,也可用于文本文件。
  • 读取位置由文件流的当前指针决定,读取后指针会自动向前移动。

3. 使用示例

以下是一些使用 fread() 的典型示例:

(1) 读取二进制数据

从文件中读取整数数组:

#include <stdio.h>

int main() {
    FILE *file = fopen("data.bin", "rb"); // 以二进制模式打开文件
    if (file == NULL) {
        printf("无法打开文件\n");
        return 1;
    }

    int buffer[5]; // 存储 5 个整数
    size_t read_count = fread(buffer, sizeof(int), 5, file); // 读取 5 个整数
    if (read_count != 5) {
        printf("读取失败,只读取了 %zu 个元素\n", read_count);
    } else {
        for (int i = 0; i < 5; i++) {
            printf("%d ", buffer[i]);
        }
    }

    fclose(file); // 关闭文件
    return 0;
}

说明

  • fopen("data.bin", "rb") 以二进制读模式打开文件。
  • fread(buffer, sizeof(int), 5, file) 尝试读取 5 个整数(每个 sizeof(int) 字节)。
  • read_count 检查实际读取的块数。
  • 输出假设文件 data.bin 包含 5 个整数的二进制数据。

(2) 读取文本数据

从文本文件中读取字符:

#include <stdio.h>

int main() {
    FILE *file = fopen("text.txt", "r"); // 以文本模式打开文件
    if (file == NULL) {
        printf("无法打开文件\n");
        return 1;
    }

    char buffer[100]; // 存储读取的字符
    size_t read_count = fread(buffer, sizeof(char), 99, file); // 读取最多 99 个字符
    buffer[read_count] = '\0'; // 手动添加字符串终止符
    printf("读取的内容:%s\n", buffer);

    fclose(file);
    return 0;
}

说明

  • 读取文本时,size 通常设为 sizeof(char)(1 字节)。
  • 读取后手动添加 \0 以确保字符串正确终止。
  • 假设 text.txt 包含文本内容。

(3) 检查文件末尾或错误

结合 feof()ferror() 检查读取状态:

#include <stdio.h>

int main() {
    FILE *file = fopen("data.bin", "rb");
    if (file == NULL) {
        printf("无法打开文件\n");
        return 1;
    }

    char buffer[10];
    size_t read_count = fread(buffer, sizeof(char), 10, file);
    if (read_count < 10) {
        if (feof(file)) {
            printf("到达文件末尾,读取了 %zu 个元素\n", read_count);
        } else if (ferror(file)) {
            printf("读取错误\n");
        }
    } else {
        printf("成功读取 %zu 个元素\n", read_count);
    }

    fclose(file);
    return 0;
}

4. 返回值与错误处理

  • 返回值
  • 如果成功读取所有请求的块,返回值等于 nmemb
  • 如果读取到文件末尾或发生错误,返回值小于 nmemb
  • 如果文件为空或立即遇到 EOF,返回 0。
  • 检查状态
  • 使用 feof(stream) 检查是否到达文件末尾。
  • 使用 ferror(stream) 检查是否发生读取错误。
  • 注意fread() 不会自动区分 EOF 和错误,需结合上述函数判断。

5. 与 Python 和 JavaScript 的对比

结合您之前询问的 Python 列表和 JavaScript 数组,这里简要对比 fread() 与相关语言的文件操作:

  • Python
  • Python 的 file.read(size)file.read() 类似 fread(),但更高级,自动处理字符编码。
  • Python 的 struct 模块可用于二进制数据解析,类似 fread() 读取固定大小的块。
  • 示例:
    python with open("data.bin", "rb") as file: data = file.read(20) # 读取 20 字节
  • JavaScript
  • 浏览器环境使用 FileReaderfetch 处理文件,Node.js 使用 fs.read()fs.readFile()
  • JavaScript 的文件操作更异步化,fread() 是同步的。
  • 示例(Node.js):
    javascript const fs = require("fs"); const buffer = Buffer.alloc(20); const fd = fs.openSync("data.bin", "r"); fs.readSync(fd, buffer, 0, 20, 0);

6. 注意事项

  • 文件模式
  • 二进制文件使用 "rb" 模式,文本文件使用 "r"
  • 不同模式可能影响读取行为(如 Windows 上的换行符处理)。
  • 缓冲区大小
  • 确保 ptr 指向的缓冲区足够大(至少 size * nmemb 字节),否则可能导致内存越界。
  • 文件指针
  • fread() 会移动文件指针,需使用 fseek()rewind() 调整位置。
  fseek(file, 0, SEEK_SET); // 将指针移到文件开头
  • 跨平台性
  • 二进制文件在不同平台上的字节序(大端/小端)可能不同,需注意数据格式。
  • 错误检查
  • 总是检查 fopen() 的返回值(是否为 NULL)。
  • 检查 fread() 的返回值以确保读取成功。

7. 与随机操作的结合

结合您之前询问的 Python random.random(),可以在 C 中使用 rand() 或其他随机函数生成数据并写入文件,再用 fread() 读取:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main() {
    srand(time(NULL)); // 初始化随机种子
    FILE *file = fopen("random.bin", "wb");
    int numbers[5];
    for (int i = 0; i < 5; i++) {
        numbers[i] = rand() % 100; // 生成 0-99 的随机数
    }
    fwrite(numbers, sizeof(int), 5, file); // 写入文件
    fclose(file);

    file = fopen("random.bin", "rb");
    int buffer[5];
    fread(buffer, sizeof(int), 5, file); // 读取随机数
    for (int i = 0; i < 5; i++) {
        printf("%d ", buffer[i]);
    }
    fclose(file);
    return 0;
}

8. 总结

fread() 是 C 语言中用于从文件读取数据的核心函数,适合处理二进制和文本数据。它通过指定块大小和数量提供灵活的读取方式,但需要手动管理文件指针和错误检查。与 Python 和 JavaScript 相比,fread() 更底层,适合需要精确控制的场景,但使用时需注意缓冲区管理和文件模式。

如果您有具体的使用场景(例如读取特定格式的二进制文件或结合随机数据处理),可以进一步提问,我会提供更详细的示例!

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注