欢迎光临
我们一直在努力

【文件操作的介绍】

文件操作的介绍

相关内容

  • 什么是文件
  • 为什么要使用文件
  • 文件的缓冲区
  • 硬盘文件,流,程序内存三者的关系
  • 文件的打开与关闭
  • 文件的顺序读写
  • 文件的随机读写
  • 文件的更新
  • 1.什么是文件

    文件的定义

    文件,是存储在外部存储设备(磁盘、U 盘、SSD)上、有名字的一组有序数据的集合,操作系统把它抽象成一个统一的访问对象,程序通过文件操作来读写这堆数据 也就是说文件就是一个存放着数据的对象 我们可以通过文件操作 借助操作系统 对其操作 我们写的程序可以叫做程序文件 带有数据的文件可以叫做数据文件

    在c语言中系统给我们了一个结构体 FILE 每个编译器里对这个结构体的定义大同小异 所以我们不用再自己定义了 直接使用即可 通过这个结构体 当我们操作文件时 我们可以创建文件信息区 用来存放文件的状态信息等 平时使用还需要用到文件指针 即FILE* 来指向这个区域

    文件名

    路径 主文件名 . 后缀 例如 D:\\new\\test.txt这样一个文件名 路径是我们查找文件的方式 后缀是文件的格式 常见的形式有:.txt .c等

    D:\\new\\ test . txt

    在c语言中我们通过文件名来指定文件 还有一个需要注意的点:路径分为绝对路径和相对路径 绝对路径就是将文件的路径全部描述出来这样来找文件 相对路径就是在 当前工作目录去找文件

    文件的一种分类(按数据存储形式)

    在c中我们把文件分为二进制文件 (内容由原始的二进制数据组成) 和 文本文件(内容由字符编码组成)

    2. 为什么要使用文件

    像我们平时在编译器中输入输出的各种数据在程序关闭后 就被清除了 不能保存下来 但是文件不会自动清除 因此我们可以利用文件 将程序产生的数据或所需要的数据存储在文件中 这样就保存了数据

    3. 文件的缓冲区

    在这里插入图片描述

    我们从文件中输入输出数据并不是一个一个依次进行的 而是有一个缓冲区 先把数据放在缓冲区里 当数据达到一定大小 再一起输入输出

    因为我们每次输入输出时都是操作系统在背后出力 如果我们每输入一个数据就让操作系统处理一次 那就太过繁琐了 所以使用了缓冲区

    4.硬盘文件,流,程序内存三者的关系

    在这里插入图片描述

    首先什么是流呢

    流是一个十分抽象的概念 他就像是充满了数据的一条小河 我们打开文件时就会创建一个流 然后将数据丢进去 再捞出来放到缓存中 最后再输入文件中 还是很有意思的

    三个标准流:stdin stdout stderr

    5.文件的打开与关闭

    现在就正式进入文件操作了!

    这里涉及了两个函数 fopen() 和 fclose() 二者都是在 <stdio.h>这个头文件中 后面的所有函数也是在这个头文件中

    关于fopen

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

    • 参数 1 filename:文件名 / 路径(相对路径、绝对路径)
    • 参数 2 mode:打开模式(文本 / 二进制,读、写、追加)

    返回值:打开成功返回 文件信息区的地址 打开失败返回 NULL 空指针 所以使用时一定要加判断看是否打开成功 否则程序可能会崩溃

    这里给出一个打开模式的表格 请读者阅读

    模式含义文件不存在文件存在
    "r" 只读(文本流) 打开失败,返回 NULL 从头读
    "w" 只写(文本流) 创建新文件 清空原有内容,从头写
    "a" 追加(文本流) 创建新文件 在文件末尾追加,原有内容保留
    "rb" 只读(二进制流) 失败 从头读
    "wb" 只写(二进制流) 创建 清空重写
    "ab" 追加(二进制流) 创建 末尾追加
    "r+" 读写(文本) 失败 可读可写
    "rb+" 读写(二进制) 失败 可读可写
    关于fclose

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

    • 参数:FILE* 文件指针(要关闭的流)
    • 返回值:成功返回 0;失败返回 EOF(-1)

    fclose 可以关闭文件信息区 同时将缓存区的数据输入输出文件 防止数据丢失

    完整的过程如下

    代码

    #include <stdio.h>
    int main()
    {
    FILE *fp = fopen("test.txt", "r");
    if(fp == NULL) // 必写判断!
    {
    perror("fopen"); // 打印打开失败原因
    return 1;
    }
    // 读写操作 …

    fclose(fp);
    fp = NULL;
    return 0;
    }

    我们创建一个文件后可以在资源管理器里打开查看

    6.文件的顺序读写

    这里涉及到四组函数依次是: fputc()和fgetc() fputs()和fgets() fprintf()和fscanf() fwrite()和fread() 其中前面三个是常用的函数

    后面一组由于控制的是二进制文本所以 用的会相对较少一些

    函数的内容有点多 但可以类比 printf 和 scanf 来记忆

    函数原型功能适用流特点、注意事项返回值示例
    fgetc int fgetc(FILE *stream); 从流中读取一个字符 文本 / 二进制流 读到的字符以unsigned char转 int 返回;读到末尾 / 出错返回 EOF 成功:读到字符(int)失败 / 到文件尾:EOF(-1) char ch = fgetc(fp);
    fputc int fputc(int ch, FILE *stream); 向流写入一个字符 文本 / 二进制流 ch 虽然是 int,只会低 8 位有效 成功:写入的字符失败:EOF fputc('A', fp);
    fgets char *fgets(char *str, int n, FILE *stream); 从流读取一行字符串 文本流 最多读n-1个字符;会把换行符\\n一起读进来,末尾自动加\\0 成功:str 地址失败 / 到末尾:NULL fgets(buf, 100, fp);
    fputs int fputs(const char *str, FILE *stream); 向流写入字符串 文本流 不会自动加换行符\\n,需要自己写\\n 成功:非负数失败:EOF fputs("hello", fp);
    fscanf int fscanf(FILE *stream, const char *format, …); 从文件按格式读取数据 文本流 用法和scanf一致,来源从文件流代替 stdin;空白符(空格、换行、Tab)自动分隔 成功:成功读到的数据个数失败 / 末尾:EOF fscanf(fp,"%d",&num);
    fprintf int fprintf(FILE *stream, const char *format, …); 按格式写入文件 文本流 用法和printf一致,输出到文件流代替 stdout 成功:输出字符总数失败:负数 fprintf(fp,"%d",num);
    fread size_t fread(void *ptr, size_t size, size_t count, FILE *stream); 从文件读取整块数据 二进制流(rb) 原样读取字节,不做换行转换;适合数组、结构体 成功:读到的元素个数小于 count:读到末尾或者出错 fread(&stu, sizeof(stu),1,fp);
    fwrite size_t fwrite(const void *ptr, size_t size, size_t count, FILE *stream); 向文件写入整块数据 二进制流(wb) 原样写入内存原始二进制,适合结构体批量保存 成功:写入的元素个数失败:小于 count fwrite(&stu, sizeof(stu),1,fp);

    这里给出其中2个示例

    我们向指文件中 输入1234 要我们能看懂肯定就是文本文件了

    代码

    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    int main() {
    FILE* pf = fopen("text.txt", "w");
    char op[10]="1234";
    if (pf == NULL) {
    perror("fopen");
    }
    fprintf(pf,"%s", op);
    fclose(pf);
    pf = NULL;
    }

    执行后从资源管理器打开文件就是这样的

    在这里插入图片描述

    而如果改成fopen("text.txt", "r");内存中 并没有这个文件 就会报错 就是这样的

    在这里插入图片描述

    如果我们要从文件中输出数据就是这样的 这里使用fgets函数 接着刚刚的操作进行 也就是说此时我们已经有一个文件text.txt了

    代码

    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    int main() {
    FILE* pf = fopen("text.txt", "r");
    char op[10] = { 0 };
    if (pf == NULL) {
    perror("fopen");
    }
    fgets(op, 4, pf);
    printf("%s", op);
    fclose(pf);
    pf = NULL;
    }

    打印出来的结果

    在这里插入图片描述

    如果在原来的1234中加一个换行12\\n34 结果就是这样的

    在这里插入图片描述
    )

    其余的大家自己可以下去试试 多注意 特点和注意事项 这里就不多展示了

    7. 文件的随机读写

    涉及的函数有 fseek() ftell() rewind()

    fseek

    函数原型 int fseek(FILE *stream, long int offset, int whence);

    参数说明
    stream FILE* 文件指针
    offset 偏移字节数,long 类型;正数向后(朝文件尾),负数向前(朝文件开头)
    whence 基准起点(三个宏)
    宏常量等价数字基准位置
    SEEK_SET 0 文件开头
    SEEK_CUR 1 文件位置指针当前位置
    SEEK_END 2 文件末尾

    作用:移动流里面的文件位置指针(读写光标),实现随机读写,不再只能从头顺序读。
    注意:这个是文件内的位置光标,不是 FILE* 文件指针!

    继续前面的例子

    代码

    #include <stdio.h>
    int main()
    {
    FILE* pf = fopen("text.txt", "rb");
    if(pf == NULL)
    {
    perror("fopen");
    return 1;
    }
    // 光标跳到开头往后偏移2字节,也就是 \\n 的位置
    fseek(pf, 2L, SEEK_SET);
    int ch = fgetc(pf);
    printf("%c", ch); // 读到 '\\n'

    fclose(pf);
    pf = NULL;
    return 0;
    }

    这里打印出的就是换行

    在这里插入图片描述

    注意:

  • **优先用于二进制文件(rb/wb)**文本文件在 Windows 下会自动做 \\n ↔ \\r\\n 换行转换,字节计数不准,fseek 偏移很容易出错!
  • 成功调用 fseek 会清除 EOF 文件结束标记,读完文件后想重新读一遍,fseek 回到头部就可以继续读。
  • ftell

    函数原型: long ftell(FILE *stream);

    作用:获取文件位置指针当前距离文件起始位置的字节偏移量

    返回值:
    成功:返回 long 类型,当前位置相对于文件开头的字节数
    失败:返回 -1L

    rewind

    函数原型:void rewind(FILE *stream);

    作用:把文件流的读写位置指针,直接重置到文件开头

    搭配 fseek 经典用法:求文件大小

    FILE* pf = fopen("test.txt", "rb");
    if(pf == NULL)
    {
    perror("fopen");
    return 1;
    }
    fseek(pf, 0L, SEEK_END); // 光标移到文件末尾
    long file_size = ftell(pf); // 获取末尾的偏移量 = 文件总字节数
    printf("文件大小:%ld 字节\\n", file_size);
    rewind(pf); // 光标回到开头,方便后续读取

    fclose(pf);

    8.文件的更新

    在这里插入图片描述

    关键要点

    fflush(FILE *stream) 可以刷新文件缓存区

  • 当我们写完文件想要读文件时一定要使用一个函数叫fflush()来刷新文件缓存区 以免数据丢失 然后在使用fseek和rewind来重置光标的位置
  • 当读完文件想要写文件时 也需要fseek和rewind
  • 这里给出一个例子

    代码

    #include <stdio.h>

    int main()
    {
    FILE* fp = fopen("test.txt", "w+");
    if (fp == NULL)
    {
    perror("fopen for w+");
    return 1;
    }
    //写abcdefghi到文件中
    fputs("abcdefghi", fp);
    //刷新缓冲区,保证数据写入文件
    fflush(fp);
    //要读取数据b字符,先定位文件指针
    fseek(fp, 1, SEEK_SET);
    int ch = fgetc(fp);//读取字符
    printf("%c\\n", ch);
    //在b的位置开始写入hello
    fseek(fp, –1, SEEK_CUR);
    //解释:因为前面读取一个字符后,文件指示器现在指向了c,需要从当前位置退回一个字符

    fputs("hello", fp);

    //关闭文件
    fclose(fp);
    fp = NULL;

    return 0;
    }

    最终文件

    在这里插入图片描述

    打印结果

    在这里插入图片描述

    以上就是本次文件操作的介绍了 内容会有点多 很多函数没有举例 还是要自己把函数的功能都实现一下才能理解本次的大致内容

    赞(0)
    未经允许不得转载:171主机测评 » 【文件操作的介绍】
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址