1.5文件操作


文件的概念

什么是文件?

文件是储存在外部介质(磁盘之类的)上数据的集合

什么是流?

操作系统是以文件为单位对数据进行管理的,输入输出是数据传送的过程,像水一样流动。所以吧输入输出称为流(stream)。输入输出流。

c语言把文件看作是字符(字节)的序列,即由一个个字符/字节组成。一个输入输出流就是一个字节流或二进制流。

文件的分类

  • ANSCll文件(文本文件):一个字节放一个ASCll码,需要转换才能读取
  • 二进制文件(视频文件等):二进制文件是由计算机可以直接读取的二进制格式表示的数据文件

文件缓冲区

文件缓冲区能够提高文件读写的速度和效率。在计算机编程中,缓冲区是一个暂时存储数据的区域,这些数据最终会被写入磁盘或从磁盘读取出来。缓冲区的主要目的是减少磁盘访问次数,因为磁盘访问通常比内存(RAM)访问慢得多。

文件缓冲区的工作原理:
写入缓冲区:

  • 当程序向文件写入数据时,这些数据首先被写入到内存中的缓冲区,而不是直接写入磁盘。
  • 缓冲区会等待直到达到某个阈值(如缓冲区满或经过一定的时间间隔)才将数据刷新到磁盘上。

读取缓冲区:

  • 当程序从文件读取数据时,数据被一次性读入到内存中的缓冲区。
  • 程序可以从缓冲区读取数据,而无需直接访问磁盘。
    在这里插入图片描述

文件指针

c语言内置的文件指针类型: 
FILE*

在标准输入输出库中,系统定义了三个FILE型的指针变量:
1. stdin (stdin): 标准输入流

  • 通常对应于用户的键盘输入。
  • 也可以被重定向到一个文件或其他输入源。
  • 可以通过 fgetc(stdin) 或 fgets(buffer, size, stdin) 等函数读取数据。

2. stdout (stdout): 标准输出流

  • 通常输出到显示器屏幕。
  • 也可以被重定向到一个文件或其他输出目的地。
  • 可以通过 fputc(c, stdout) 或 printf 函数写入数据。

3. stderr (stderr): 标准错误输出流

  • 用于输出错误信息或诊断信息。
  • 通常也是输出到显示器屏幕,但它独立于标准输出流。
  • 这意味着即使标准输出被重定向,标准错误输出仍然可以输出到屏幕或其他地方。
  • 可以通过 fprintf(stderr, …), fputs(…, stderr) 或 fputc(…, stderr) 写入数据。

文件位置指针

用来指示当前文件读写位置。


文件操作

文件的打开与关闭

  • 文件的打开
    在C语言中,文件的打开是通过fopen函数实现的。这个函数接受两个参数:文件名和打开模式。打开模式决定了文件的读写权限以及文件是否会被创建或截断。fopen函数的原型如下:
    FILE *fopen(const char *filename, const char *mode);
//fopen函数调用后需要检测返回值,保证程序的健壮性
FILE* file = fopen("E:/text.txt","w");
if (file == NULL) {
        fprintf(stderr, "Error opening source file: %s\n", file);
        //或者用perror();也ok
        return 1;
    }
其中filename是要打开的文件的名称(文件路径),mode是一个字符串,指定了文件的打开方式。
  • 文件的关闭
    文件关闭是通过fclose函数实现的,它接受一个FILE类型的指针作为参数,该指针是由fopen函数返回的。调用fclose函数会关闭与之关联的文件,并释放所有相关资源。fclose函数的原型如下:
    int fclose(FILE *stream);
    如果文件关闭成功,fclose返回0;如果发生错误,返回非零值。

文件路径

  • 绝对路径:文件的在磁盘中的实际路径。
    FILE* file = fopen("E:/VSfile/Project/test.txt", "w");
  • 相对路径:相对于程序运行位置的路径。可用“./”表示相对路径的开始,也可省略。
    FILE* file = fopen("test.txt", "w");

    FILE* file = fopen("./test.txt", "w");
文件路径分隔符
  • Windows: 使用反斜杠(\)作为分隔符。例如,“C:\Users\Username\Documents\file.txt”。
  • UNIX/Linux/macOS: 使用正斜杠(/)作为分隔符。例如,“/home/username/Documents/file.txt”。
  • 注意:在C语言字符串中,反斜杠(\)有特殊意义,用作转义字符。因此,在Windows文件路径中,需要用==两个反斜杠(\)==来表示一个实际的反斜杠。
    跨平台文件路径处理:
  • 通用方法:使用正斜杠(/)作为分隔符,因为它在大多数操作系统中都是可接受的。
    特定于平台的方法:可以定义宏来选择适当的分隔符。例如,定义 PATH_SEPARATOR 宏,在Windows中设为反斜杠(\),在其他系统中设为正斜杠(/)。

常用的文件打开模式

模式含义说明
r只读文件必须存在,否则打开失败
w只写(覆盖写)若文件存在,则清除原文件内容后写入;否则,创建文件后写入
a追加只写若文件存在,则位置指针移到文件末尾,在文件尾部追加写入,故该方式不删除原文件数据;若文件不存在,则创建文件并追加写入
r+读写文件必须存在。在只读 r 的基础上加 + 表示增加可写的功能
w+读写在只写 w 的基础上加 + 表示增加可读的功能
a+读写a 模式的基础上,增加可读功能
rb二进制读功能同模式 r,区别:b 表示以二进制模式打开
wb二进制写功能同模式 w。二进制模式
ab二进制追加功能同模式 a。二进制模式
rb+二进制读写功能同模式 r+。二进制模式
wb+二进制读写功能同模式 w+。二进制模式
ab+二进制读写功能同模式 a+。二进制模式

读写 相关函数

字符串的写入与读出

getc / putc 函数 , fscanf / fprintf 函数 , fgets / fgets 函数 , 只能用于操作 文本文件 ;

函数名用途语法示例
fputc写入单个字符到文件int fputc(int c, FILE *stream);fputc('A', file);
fgetc从文件读取单个字符int fgetc(FILE *stream);int ch = fgetc(file);
fputs写入字符串到文件int fputs(const char *s, FILE *stream);char str[] = "Hello\n"; fputs(str, file);
fgets从文件读取一行文本char *fgets(char *s, int _MaxCount, FILE *stream);char line[100];fgets(line, 100, file);
fprintf格式化写入数据到文件int fprintf(FILE *stream, const char *format, ...);fprintf(file, "Hello, %s!", "world");
fwrite写入数据块到文件size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);char data[] = "Binary data";fwrite(data, sizeof(char), strlen(data), file);
  • 读字符串函数fgets
    fgets() 函数用来从指定的文件中读取一个字符串,并保存到字符数组中,它的用法为:
    char* fgets (char* _Buffer,int _MaxCount,FILE* _Stream);
    .buffer为字符数组
    ·maxcount为要读取的字符数量(不要超过buffer字符数组的大小)
    ·stream 文件指针
    返回值:
    读取成功时返回字符数组首地址,也就是buffer;读取失败时返回NULL;如果开始读取时文件内部指针已经指向了文件末尾,那么将读取不到任何字符,也返回 NULL.
    ·需要重点说明的是,在读取到MaxCount-1个字符之前如果出现了换行,或者读到了文件末尾则读取结束。这就意味着,不管 MaxCount的值多大,fgets()最多只能读取一行数据,不能跨行。在C语言中,没有按行读取文件的函数,我们可以借助fgets(),将 MaxCount的值设置地足够大,每次就可以读取到一行数据。
用fgets函数读取整个文件
    char buff[20];
    while (feof(file)==0)
    {
        fgets(buff, 20, file);
        printf("%s", buff);
    }
  • 写字符串函数fputs
    返回0表示成功,否则表示失败返回错误信息。
if (feof(file)) {
    printf("End of file reached.\n");
}
文件的格式化读写
函数名用途语法特点/用途
fprintf格式化写入数据到文件int fprintf(FILE *stream, const char *format, ...);类似于 printf,但目标是文件也可是标准输出。
fscanf从文件格式化读取数据int fscanf(FILE *stream, const char *format, ...);类似于 scanf,输入流较灵活。
printf格式化输出到标准输出int printf(const char *format, ...);用于将格式化的数据输出到标准输出(通常是屏幕)。
scanf从标准输入格式化读取数据int scanf(const char *format, ...);用于从标准输入(通常是键盘)读取格式化的数据。
二进制文件的读写

fread / fwrite 函数 既可以操作 二进制文件 , 又可以操作 文本文件 ; 但在打开对应文件时中文文本大概率乱码 乱码详解——CSDN

解决:若用记事本打开可以另存为选择ANSI保存就不会乱码了。

fgets()有局限性,每次最多只能读取文件的一行数据,如果想要读取多行内容,需要使用fread()函数。写入类似,对应使用fwrite。

函数名用途语法
fwrite从指定内存缓冲区中写入若干字节数据到文件size_t fwrite(void const* _Buffer, size_t _ElementSize,size_t _ElementCount,FILE* _Stream)
fread从文件中读取若干字节数据到指定内存缓冲区中 ;size_t fread( void* _Buffer,size_t _ElementSize,size_t _ElementCount, FILE* _Stream)
  • fwrite()与fread()
    对参数的说明:
  1. Buffer为内存区块的指针,它可以是数组、变量、结构体等。fread()中的 Bufer用来存放读取到的数据,fwrite() 中的 Bufer用来存放要写入的数据
  2. ElementSize:表示每个数据块的字节数
  3. ElementCount:表示要谈写的数据块的块数。
  4. Stream:表示文件指针。
    。理论上,每次读写 size*count 个字节的数据
    返回值:返回成功读写的块数,也即count,如果返回值小于count:
    。对于 fwrite() 来说,肯定发生了写入错误,可以用ferror()函数检测,
    。对于 fread() 来说,可能读到了文件末尾,可能发生了错误,可以用 ferror()或 feof() 检测,
    fread\fwrite细节讲解_b站
    fread函数的具体用法与实例(推荐)

随机读写

函数名用途语法
rewind用于将位置指针移动到文件开头void rewind(FILE* Stream);
fseek用于将位置指针移动到特定位置int fseek(FILE *Stream, long offset, int origin);
ftell返回给定流 stream 的当前文件位置(可用于计算文件大小)long int ftell(FILE *stream)

如何用retell计算文件大小

参数说明:

  • offset为偏移量,也就是要移动的字节数。(offset为正,向origin位置后移动。为负,向前)
  • origin为起始位置(偏移量的基准点)
  • fseek()返回0表示成功非零表示失败

C语言规定了三种起始位置,分别有对应常量

起始点常量名常量值
文件开头SEEK_SET0
当前位置SEEK_CUR1
文件末尾SEEK_END2

文件拷贝

字符串拷贝与二进制文件拷贝
教程
介绍了main函数argv参数的用法,配合上二进制读写函数实现图片拷贝。
演示代码_CSDN


状态判断 相关函数

函数名用途语法
feof检查文件是否到达文件末尾int feof(FILE *stream);
  • feof()
    用途: feof 函数用于检查文件流是否已经到达文件末尾。End Of File
    语法: int feof(FILE *stream);
    返回值: 如果文件流已经到达文件末尾,则返回非零值;否则返回0。

错误的检查与输出 相关函数

函数名用途语法
perror打印错误消息void perror(const char *s);
ferror检查文件流错误状态int ferror(FILE *stream);
  • perror()
    用途: perror 函数用于打印一个错误消息到标准错误输出(通常是终端),并且它还会打印出与错误相关的系统错误号及其描述
    语法: void perror(const char *s);
    参数: s 是一个字符串,通常包含一些上下文信息,比如文件名或者操作名称。

  • ferror()
    用途: ferror 函数用于检查上一次对文件流的操作是否产生了错误
    语法: int ferror(FILE *stream);
    返回值: 如果上一次操作产生错误,则返回非零值;否则返回0。

两个函数可以结合使用 
如:
if (ferror(file)) {
    perror("Error writing to file");
}

重定向

  • 重定向输入:一般用scanf从键盘读取,也可从文件读取如: main.exe <test.txt (这里<可以看作文件流动的方向,从文件到程序)
  • 重定向输出:一般用printf想屏幕输出,也可向文件写入:main.exe >test.txt

还可用freopen函数进行重定向。
详解重定向

  • 20
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值