C 文件读写

C语言文件读写完全指南

C语言文件读写完全指南

编程小白也能轻松理解的文件操作知识点汇总

一、文件基础概念

什么是文件?

文件是存储在计算机硬盘、U盘等存储设备上的一组相关数据的集合。就像你电脑里的Word文档、照片、音乐一样。

文本文件 vs 二进制文件

文本文件:内容是人类可读的字符(字母、数字、标点),可以用记事本打开查看。例如:.txt, .c, .html文件。

二进制文件:内容是给计算机看的0和1序列,人类直接看不懂。例如:.exe, .jpg, .mp3文件。

文件指针(FILE指针)

在C语言中,我们通过一个叫FILE指针的东西来操作文件。你可以把它想象成一个遥控器,通过这个遥控器你可以控制文件的各种操作。

每次操作文件前,你需要先获得这个”遥控器”(打开文件),用完后再把它归还(关闭文件)。

// 声明一个文件指针
FILE *file_ptr;

二、文件的打开与关闭

fopen() – 打开文件

就像开门进房间一样,使用文件前需要先打开它。

函数原型: FILE *fopen(const char *filename, const char *mode);

参数说明:

  • filename – 文件路径(如:”test.txt”)
  • mode – 打开模式(如:”r”表示只读)

文件打开模式

模式 说明 文件不存在 文件存在
“r” 只读(文本文件) 打开失败 打开成功
“w” 只写(文本文件) 创建新文件 清空原有内容
“a” 追加(文本文件) 创建新文件 在末尾添加内容
“r+” 读写(文本文件) 打开失败 打开成功
“rb” 只读(二进制文件) 打开失败 打开成功
“wb” 只写(二进制文件) 创建新文件 清空原有内容

fclose() – 关闭文件

就像离开房间要关门一样,用完文件后一定要关闭它!

函数原型: int fclose(FILE *stream);

关闭成功返回0,失败返回EOF(-1)

// 打开和关闭文件的示例
FILE *fp = fopen(“example.txt”, “w”); // 以写入方式打开

// 检查文件是否成功打开
if(fp == NULL) {
    printf(“打开文件失败!\n”);
    return 1;
}

// 文件操作代码…

fclose(fp); // 关闭文件
fp = NULL; // 将指针设为NULL防止误用

重要提示:

1. 每次打开文件后一定要检查是否成功(指针是否为NULL)

2. 操作完成后必须关闭文件,否则可能导致数据丢失或文件损坏

3. 关闭文件后最好将指针设为NULL,避免野指针问题

三、文件读写操作

文本文件读写函数

函数 作用 类比 示例
fgetc() 读取单个字符 从文件中一个字一个字地读 char c = fgetc(fp);
fputc() 写入单个字符 往文件中一个字一个字地写 fputc(‘A’, fp);
fgets() 读取一行字符串 从文件中一行一行地读 fgets(str, 100, fp);
fputs() 写入字符串 往文件中写一段文字 fputs(“Hello”, fp);
fscanf() 格式化读取 按特定格式从文件读取数据 fscanf(fp, “%d %f”, &num, &price);
fprintf() 格式化写入 按特定格式将数据写入文件 fprintf(fp, “ID: %d, Price: %.2f”, id, price);

文本文件读写示例

// 写入文本文件
FILE *write_fp = fopen(“diary.txt”, “w”);
if(write_fp) {
    fprintf(write_fp, “2023年10月25日 晴\n”);
    fprintf(write_fp, “今天学习了C语言文件操作\n”);
    fputs(“感觉收获满满!”, write_fp);
    fclose(write_fp);
}

// 读取文本文件
FILE *read_fp = fopen(“diary.txt”, “r”);
if(read_fp) {
    char buffer[100];
    while(fgets(buffer, 100, read_fp) != NULL) {
        printf(“%s”, buffer);
    }
    fclose(read_fp);
}

四、二进制文件操作

二进制文件操作适合处理非文本数据,如图片、音频、视频或自定义数据结构。

二进制读写函数

函数 作用 参数说明
fread() 从文件读取数据到内存 fread(存储位置, 每块大小, 块数, 文件指针)
fwrite() 将内存数据写入文件 fwrite(数据地址, 每块大小, 块数, 文件指针)

二进制文件读写示例

// 定义学生结构体
struct Student {
    int id;
    char name[20];
    float score;
};

// 写入二进制文件
FILE *bin_fp = fopen(“students.dat”, “wb”);
if(bin_fp) {
    struct Student stu1 = {101, “张三”, 87.5};
    struct Student stu2 = {102, “李四”, 92.0};

    fwrite(&stu1, sizeof(struct Student), 1, bin_fp);
    fwrite(&stu2, sizeof(struct Student), 1, bin_fp);
    fclose(bin_fp);
}

// 读取二进制文件
bin_fp = fopen(“students.dat”, “rb”);
if(bin_fp) {
    struct Student stu;
    while(fread(&stu, sizeof(struct Student), 1, bin_fp) == 1) {
        printf(“学号: %d, 姓名: %s, 分数: %.1f\n”, stu.id, stu.name, stu.score);
    }
    fclose(bin_fp);
}

二进制文件操作小贴士:

✓ 使用sizeof运算符获取数据类型大小

✓ 检查fread/fwrite的返回值,确保读写正确数量的数据块

✓ 二进制文件不能用文本编辑器查看内容

✓ 二进制文件通常比文本文件更节省空间

五、文件定位操作

文件内部有一个”光标”(位置指针),指示当前读写位置。通过文件定位函数可以移动这个”光标”。

文件定位函数

函数 作用 示例
fseek() 移动文件位置指针 fseek(fp, 10, SEEK_SET);
ftell() 获取当前指针位置 long pos = ftell(fp);
rewind() 将指针重置到文件开头 rewind(fp);

fseek参数详解

int fseek(FILE *stream, long offset, int whence);

offset: 偏移量(字节数)

whence: 基准位置

  • SEEK_SET – 文件开头
  • SEEK_CUR – 当前位置
  • SEEK_END – 文件末尾
// 文件定位示例
FILE *fp = fopen(“data.txt”, “r”);
if(fp) {
    fseek(fp, 0, SEEK_END); // 移动到文件末尾
    long size = ftell(fp); // 获取文件大小
    printf(“文件大小: %ld 字节\n”, size);

    rewind(fp); // 回到文件开头

    // 读取第11个字节开始的10个字符
    fseek(fp, 10, SEEK_SET);
    char buffer[11];
    fread(buffer, 1, 10, fp);
    buffer[10] = ‘\0’;
    printf(“内容: %s\n”, buffer);

    fclose(fp);
}

六、错误处理与状态检测

文件操作可能失败,好的程序应该能处理错误情况。

错误处理函数

函数 作用 返回值
feof() 检测是否到达文件末尾 非0值表示到达末尾
ferror() 检测文件操作是否出错 非0值表示出错
perror() 打印错误信息
// 错误处理示例
FILE *fp = fopen(“nonexistent.txt”, “r”);
if(fp == NULL) {
    perror(“打开文件失败”); // 输出: 打开文件失败: No such file or directory
}

// 读取文件时的错误处理
while(!feof(fp)) {
    char c = fgetc(fp);
    if(ferror(fp)) {
        printf(“读取文件时出错!\n”);
        clearerr(fp); // 清除错误标志
        break;
    }
    printf(“%c”, c);
}

重要注意事项:

1. 不要使用feof()作为循环条件,应该在循环内检查

2. 文件操作失败后,使用perror()可以获取详细的错误信息

3. ferror()检测到错误后,可以使用clearerr()清除错误标志

4. 文件操作可能因权限不足、磁盘满、文件被占用等原因失败

七、完整示例:学生成绩管理系统

// 学生成绩管理系统简化版
#include <stdio.h>

struct Student {
    int id;
    char name[20];
    float score;
};

void addStudent() {
    FILE *fp = fopen(“students.dat”, “ab”); // 追加模式
    if(!fp) {
        perror(“打开文件失败”);
        return;
    }

    struct Student stu;
    printf(“输入学号: “);
    scanf(“%d”, &stu.id);
    printf(“输入姓名: “);
    scanf(“%s”, stu.name);
    printf(“输入分数: “);
    scanf(“%f”, &stu.score);

    fwrite(&stu, sizeof(stu), 1, fp);
    fclose(fp);
    printf(“添加成功!\n”);
}

void listStudents() {
    FILE *fp = fopen(“students.dat”, “rb”);
    if(!fp) {
        printf(“没有学生记录\n”);
        return;
    }

    struct Student stu;
    printf(“学号\t姓名\t分数\n”);
    printf(“——————\n”);

    while(fread(&stu, sizeof(stu), 1, fp) == 1) {
        printf(“%d\t%s\t%.1f\n”, stu.id, stu.name, stu.score);
    }

    fclose(fp);
}

int main() {
    int choice;

    do {
        printf(“\n学生成绩管理系统\n”);
        printf(“1. 添加学生\n”);
        printf(“2. 列出学生\n”);
        printf(“0. 退出\n”);
        printf(“请选择: “);
        scanf(“%d”, &choice);

        switch(choice) {
            case 1: addStudent(); break;
            case 2: listStudents(); break;
            case 0: printf(“再见!\n”); break;
            default: printf(“无效选择\n”);
        }
    } while(choice != 0);

    return 0;
}

实际开发建议:

✓ 文件操作完成后立即关闭文件

✓ 重要数据操作后考虑使用fflush()强制写入

✓ 对于大型文件,考虑分块读写而不是一次性读入内存

✓ 使用二进制文件存储结构化数据更高效

✓ 考虑文件路径的跨平台兼容性(Windows用\,Linux用/)

© 2023 C语言文件操作指南 | 编程小白也能懂的详细教程

提示:实际编程时请根据具体需求选择合适的文件操作方式

发表评论

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

滚动至顶部