一、基本流程

1. 定义文件指针的基本语法

FILE *fp;

2. 打开文件:fopen()

打开文件时需要指定文件路径和打开模式:

FILE *fp = fopen("example.txt", "w");

⚠️调用 fopen 后必须检查返回值是否为 NULL (例如文件不存在或权限不足会导致打开失败)

3. 关闭文件:fclose()

完成操作后,务必关闭文件以释放资源并确保缓存区的数据写入磁盘

fclose(fp);

二、常用文件打开模式

模式含义说明
r只读文件必须存在;若不存在,返回 NULL
w只写覆盖写入;文件若存在则清空,不存在则创建
a追加从文件末尾接着写;文件不存在则创建
r+读写文件必须存在,可读可写
w+读写清空并创建可读可写的文件
a+读写/追加追加写,可读;文件不存在则创建

如果是二进制文件(如图片、视频),在模式后加 b 即可,e.g. rb,wb.

三、读写文件的3种常见方式

1. 文本按行读写(最常见:fputs / fgets

写入一行:

#include <stdio.h>

int main() {
    FILE *fp = fopen("test.txt", "w");
    if (fp == NULL) {
        printf("无法打开文件!\n");
        return 1;
    }

    fputs("Hello World!\n", fp);
    fputs("GrizzlyBlog\n", fp);

    fclose(fp);
    return 0;
}

读取一行:

#include <stdio.h>

int main() {
    FILE *fp = fopen("test.txt", "r");
    if (fp == NULL) {
        printf("无法打开文件!\n");
        return 1;
    }

    char buffer[100];
    // 循环读取每一行,直到 EOF (文件末尾)
    while (fgets(buffer, sizeof(buffer), fp) != NULL) {
        printf("%s", buffer);
    }

    fclose(fp);
    return 0;
}

2. 格式化读写(类似于 printf / scanf

使用 fprintffscanf 可以非常方便地保存和读取结构化数据.

①格式化写入:fprintf()

FILE *fp = fopen("data.txt", "w");
int age = 20;
char name[] = "Grizzly";

fprintf(fp, "Name: %s, Age: %d\n", name, age);
fclose(fp);

②格式化读取:fscanf()

FILE *fp = fopen("data.txt", "r");
char name[20];
int age;

// 从文件中提取数据并存入变量
fscanf(fp, "Name: %s, Age: %d", name, &age);
printf("解析结果: 姓名=%s, 年龄=%d\n", name, age);

fclose(fp);

3. 二进制数据读写(fwrite / fread

如果你需要保存数组、结构体等二进制数据,可以使用 fwritefread

#include <stdio.h>

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

int main() {
    Student s1 = {101, "Bob", 95.5f};

    // 1. 以二进制写入模式打开
    FILE *fp = fopen("student.dat", "wb");
    fwrite(&s1, sizeof(Student), 1, fp); // 写入 1 个结构体
    fclose(fp);

    // 2. 以二进制读取模式打开
    Student s2;
    fp = fopen("student.dat", "rb");
    fread(&s2, sizeof(Student), 1, fp);  // 读取 1 个结构体
    fclose(fp);

    printf("读取结构体: ID=%d, 姓名=%s, 成绩=%.1f\n", s2.id, s2.name, s2.score);
    return 0;
}

四、文件指针定位(随机访问)

跳到文件的特定位置进行读写常用函数:

1.fseek():移动文件指针到指定位置

语法定义:

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

stream:文件指针 offset:偏移量(要移动多少个字节).正数表示往后移,负数表示往前移. origin:基准位置(从哪里开始算偏移量)包括: ① SEEK_SET :从文件开头算 ② SEEK_CUR :从当前位置算 ③ **SEEK_END **:从文件末尾算

// 1. 跳到文件开头往后第 10 个字节的位置
fseek(fp, 10, SEEK_SET);

// 2. 从当前位置再往后跳 5 个字节
fseek(fp, 5, SEEK_CUR);

// 3. 跳到文件末尾(常用于准备追加,或结合 ftell 计算文件大小)
fseek(fp, 0, SEEK_END);

// 4. 跳到文件倒数第 10 个字节的位置
fseek(fp, -10, SEEK_END);

2. ftell():获取当前位置

语法定义:

long ftell(FILE *stream);

应用:获取文件大小先用 fseek 拖到最末尾,再用 ftell 看当前位置,结果就是文件的总字节数:

fseek(fp, 0, SEEK_END); // 1. 移到文件最末尾
long fileSize = ftell(fp); // 2. 获取当前位置,即文件总大小(字节)
printf("文件大小为: %ld 字节\n", fileSize);

3. rewind():重置文件指针

语法定义:

void rewind(FILE *stream);

等同于执行:

fseek(fp, 0, SEEK_SET);

**使用场景:**当程序先读了一遍文件来统计行数,统计完后,想再读一遍文件把内容存进数组里。如果不把指针重置回开头,第二次读取就会直接读到文件末尾(EOF),什么也读不到。这时候调用一下 rewind(fp); 就能重新从头读起.

4. 实例:计算文件大小

FILE *fp = fopen("test.txt", "r");
if (fp != NULL) {
    fseek(fp, 0, SEEK_END); // 指针移到结尾
    long size = ftell(fp);   // 获取当前偏移量(即文件字节数)
    printf("文件大小: %ld 字节\n", size);
    fclose(fp);
}