C语言:文件操作

我们使用文件的原因是:想要把数据直接存放在电脑的硬盘上面,实现数据的持久化

一、什么是文件?

  1. 程序文件

    程序文件主要指的是由程序开发产生的文件,包括:

    • 源程序文件 :包含代码的文件,扩展名通常为 .c
    • 目标文件 :由编译器将源代码编译生成的中间文件,扩展名通常为 .obj(在Windows系统上)(linux的我之前写过来着)
    • 可执行文件 :由链接器生成的最终可以直接运行的文件,扩展名为 .exe
  2. 数据文件

    数据文件是存储数据的文件 ,数据可以是程序运行时 产生的或需要读入程序中的。它们的内容可以是文本、数字、二进制数据等

  3. 文件名

    文件名通常包括文件路径、文件名主干和文件后缀:

    • 文件路径:指定文件所在的目录位置(如 C:/Documents
    • 文件名主干:文件的主要名称部分(如 myfile
    • 文件后缀:文件的类型标识(如 .txt.bin

二、文件的打开和关闭

  1. 文件指针

    在C语言中,每个文件在被打开时,系统会在内存中为该文件分配一个文件信息区 。这个文件信息区存储了与文件相关的信息,包括文件名、文件指针位置、文件状态等。为了操作这些文件信息,我们通过一个类型为 FILE 的结构体指针来引用文件

    • FILE 是由标准库定义的结构体类型,包含了文件的状态信息。不同编译器对 FILE 结构体的定义可能略有不同,但其作用一致。
  2. 文件的打开和关闭

    使用 fopen 函数打开文件,使用 fclose 函数关闭文件

    FILE *fopen(const char *filename, const char *mode);
    int fclose(FILE *stream);
    

    filename:文件的名称(包括路径)
    mode:文件的打开方式,如下:

    • "r":以只读方式打开文件,文件必须存在
    • "w":以写入方式打开文件,若文件存在则覆盖,不存在则创建
    • "a":以追加方式打开文件,若文件存在则在文件末尾追加,不存在则创建
    • "rb":以二进制模式读取文件
    • "wb":以二进制模式写入文件
    • "r+":以读写模式打开文件,文件必须存在
    • "w+":以读写模式打开文件,如果文件存在则清空内容,如果不存在则创建
    • 类型挺多的,你记住如果文件不存在就报错的有:r、rb、ab、r+、rb+就行

    #include <stdio.h>

    int main() {
    // 打开文件 example.txt,使用 "r" 模式,表示只读
    FILE *fp = fopen("example.txt", "r");
    if (fp == NULL) {
    // 错误处理,如果文件打开失败,返回1
    printf("无法打开文件\n");
    return 1;
    }

     // 文件操作部分(如读取、写入)
     
     // 关闭文件,释放资源
     fclose(fp);
     return 0;
    

    }

三、文件的顺序读写

文件的顺序读写是指从文件的开头开始按顺序进行读写操作,常用函数包括 freadfwritefgetsfputs

读操作

  • fgetc():从文件中读取一个字符

  • fgets():从文件中读取一行文本

  • fread():从文件中读取一块数据

    #include <stdio.h>

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

      char ch;
      // 使用 fgetc 逐字符读取文件内容
      while ((ch = fgetc(fp)) != EOF) {
          putchar(ch);  // 将读取的字符输出到控制台
      }
    
      fclose(fp);
      return 0;
    

    }

这里,fgets 从文件中读取一行,并存储在 buffer 中,直到遇到换行符或者达到 sizeof(buffer)

#include <stdio.h>

int main() {
    FILE *fp = fopen("example.txt", "r");
    if (fp == NULL) {
        perror("无法打开文件");
        return 1;
    }

    char buffer[256];
    while (fgets(buffer, sizeof(buffer), fp) != NULL) {
        printf("%s", buffer);
    }

    fclose(fp);
    return 0;
}

写操作

  • fputc():向文件中写入一个字符

  • fputs():向文件中写入一个字符串

  • fwrite():向文件中写入一块数据

    #include <stdio.h>

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

      // 使用 fputs 写入字符串到文件
      fputs("Hello, world!\n", fp);
    
      fclose(fp);
      return 0;
    

    }

四、文件的随机读写

在文件的任意位置读写称为随机读写,C语言提供了三个函数用于文件的定位和读取:

fseek()
fseek() 函数用于移动文件指针到文件中的某个位置:

int fseek(FILE *stream, long offset, int whence);
  • stream:文件指针
  • offset:移动的字节数
  • whence:指针移动的基准位置:
    • SEEK_SET:文件开头
    • SEEK_CUR:当前文件指针位置
    • SEEK_END:文件末尾

ftell()
ftell() 返回文件指针当前的位置:

long ftell(FILE *stream);

rewind()
rewind() 函数将文件指针移回文件开头

void rewind(FILE *stream);

举个例子:

#include <stdio.h>

int main() {
    FILE *fp = fopen("example.txt", "r");
    if (fp == NULL) {
        printf("无法打开文件\n");
        return 1;
    }
    fseek(fp, 10, SEEK_SET);  // 将文件指针移动到文件开头之后的第10个字节
    char ch = fgetc(fp);
    printf("字符:%c\n", ch);
    fclose(fp);
    return 0;
}

下面是对 ftellfseek 的使用示例:

#include <stdio.h>

int main() {
    FILE *fp = fopen("example.txt", "r");
    if (fp == NULL) {
        perror("无法打开文件");
        return 1;
    }

    fseek(fp, 0, SEEK_END);  // 移动到文件末尾
    long size = ftell(fp);   // 获取文件大小
    printf("文件大小: %ld 字节\n", size);

    rewind(fp);  // 返回文件开头
    char ch;
    while ((ch = fgetc(fp)) != EOF) {
        putchar(ch);
    }

    fclose(fp);
    return 0;
}

这里使用 fseek 将文件指针移动到文件末尾,并用 ftell 获取文件大小

五、文本文件和二进制文件

  1. 文本文件

    文本文件是指存储文本数据的文件,每个字符以ASCII码的形式存储。常用的操作模式包括 "r""w"

  2. 二进制文件

    二进制文件直接存储数据的二进制格式,可以包含任意类型的文件。其操作模式包括 "rb""wb"

    #include <stdio.h>
    
    int main() {
        // 写入二进制文件
        FILE *fp = fopen("example.bin", "wb");
        if (fp == NULL) {
            printf("无法打开文件\n");
            return 1;
        }
        int num = 12345;
        fwrite(&num, sizeof(int), 1, fp);  // 将整型变量写入文件
        fclose(fp);
    
        // 读取二进制文件
        fp = fopen("example.bin", "rb");
        if (fp == NULL) {
            printf("无法打开文件\n");
            return 1;
        }
        int read_num;
        fread(&read_num, sizeof(int), 1, fp);  // 从文件读取整型变量
        printf("读取的数字是:%d\n", read_num);
        fclose(fp);
    
        return 0;
    }
    

六、文件读取结束的判定

在读取文件时,经常需要判断文件是否已到末尾,feof() 是常用的判断函数

int feof(FILE *stream);

feof() 当文件指针到达文件末尾时返回非0值,否则返回0。但需要注意的是,feof() 只有在尝试读取后才会返回EOF状态,不能在读取前判断

#include <stdio.h>

int main() {
    FILE *fp = fopen("example.txt", "r");
    if (fp == NULL) {
        printf("无法打开文件\n");
        return 1;
    }
    while (!feof(fp)) {
        char ch = fgetc(fp);
        if (feof(fp)) break;  // 读取后判断是否到达文件末尾
        putchar(ch);
    }
    fclose(fp);
    return 0;
}

七、文件缓冲区

文件缓冲区的存在有助于提升程序的性能,降低系统调用频率,同时提高数据一致性和安全性,并提供了灵活的控制机制

C语言中的文件操作默认是缓冲的,使用 setbuf()setvbuf() 函数可以控制文件缓冲行为。文件缓冲分为三种模式:

  1. 全缓冲:数据积累到缓冲区满时才会写入。

  2. 行缓冲:遇到换行符时数据会写入。

  3. 无缓冲:每次操作都会立即写入或读取

    #include <stdio.h>

    int main() {
    FILE *fp = fopen("example.txt", "w");
    if (fp == NULL) {
    perror("无法打开文件");
    return 1;
    }

     char buf[BUFSIZ];
     setvbuf(fp, buf, _IOFBF, BUFSIZ);  // 设置为全缓冲模式
    
     fputs("缓冲写入测试\n", fp);
    
     fclose(fp);
     return 0;
    

    }

因为有缓冲区存在,所以在C语言操作文件的时候,需要做刷新缓冲区或者在文件操作结束的时候关闭文件

相关推荐
Ajiang282473530439 分钟前
对于C++中stack和queue的认识以及priority_queue的模拟实现
开发语言·c++
幽兰的天空44 分钟前
Python 中的模式匹配:深入了解 match 语句
开发语言·python
Theodore_10224 小时前
4 设计模式原则之接口隔离原则
java·开发语言·设计模式·java-ee·接口隔离原则·javaee
网易独家音乐人Mike Zhou4 小时前
【卡尔曼滤波】数据预测Prediction观测器的理论推导及应用 C语言、Python实现(Kalman Filter)
c语言·python·单片机·物联网·算法·嵌入式·iot
----云烟----6 小时前
QT中QString类的各种使用
开发语言·qt
lsx2024066 小时前
SQL SELECT 语句:基础与进阶应用
开发语言
开心工作室_kaic6 小时前
ssm161基于web的资源共享平台的共享与开发+jsp(论文+源码)_kaic
java·开发语言·前端
向宇it6 小时前
【unity小技巧】unity 什么是反射?反射的作用?反射的使用场景?反射的缺点?常用的反射操作?反射常见示例
开发语言·游戏·unity·c#·游戏引擎
武子康6 小时前
Java-06 深入浅出 MyBatis - 一对一模型 SqlMapConfig 与 Mapper 详细讲解测试
java·开发语言·数据仓库·sql·mybatis·springboot·springcloud
转世成为计算机大神7 小时前
易考八股文之Java中的设计模式?
java·开发语言·设计模式