C语言文件读写操作/标准IO

本文详细介绍了C语言中文件读写的操作方法,包括使用fopen()打开文件、getc()逐字符读取、putc()写入字符,以及标准IO流程中的缓冲区原理。通过实例演示了如何通过stdio库进行文件操作,特别关注了缓冲区的作用和注意事项。
摘要由CSDN通过智能技术生成

C语言文件读写操作

参考《C Primer Plus 第六版(中文版)》

读文件

  • 读文件
#include "stdio.h"
#define TEST_FILE_PATH "TestFile.txt"//测试文件路径

int main(void)
{
    int character;//用于存储读取到的单个字符
    FILE* file_pointer;//文件指针,其中FILE是一个结构体,于是file_pointer是一个结构体指针
    
    //fopen()函数打开文件,将函数返回的文件信息结构体指针赋值给结构体指针变量file_pointer
    file_pointer = fopen(TEST_FILE_PATH,"r");
    /* 后面的"r"是打开文件的模式 */
    
    //进入逐字符读取循环前首先判定文件是否为空文件(getc()函数将逐字符读取数据,读到文件末尾时将返回EOF,EOF值为-1)
    while((character = getc(file_pointer)) != EOF)
    {
        printf("%c",character);//将读到的字符连续打印出来
    }
    fclose(file_pointer);//关闭指定文件
    printf("\nOutput end!\n");//输出完毕
    
    return 0;
}
  • 关于FILE

以下是FILE结构体的定义

typedef struct _iobuf
{
  char	*_ptr;
  int	 _cnt;
  char	*_base;
  int	 _flag;
  int	 _file;
  int	 _charbuf;
  int	 _bufsiz;
  char	*_tmpfname;
} FILE;

不大清除这些数据都是啥,但是可以知道的是,它是一个“文件信息的填写模板”,在上面读文件的代码中,file_pointer就是一个指向这种结构体的指针fopen()函数打开文件后返回“一张单子”(FILE类型结构体指针),这张单子包含我们操作的这个文件的缓冲区信息(个人理解是:fopen()函数读取文件需要将文件数据读取到缓冲区,然后返回文件数据在缓冲区的位置信息返回出去)。

根据文件数据的位置信息,我们可以读取到文件数据。

  • 关于fopen()

getc()putc()函数与getchar()putchar()函数类似。所不同的是,要告诉
getc()putc()函数使用哪一个文件。下面这条语句的意思是“从标准输入中
获取一个字符”:
ch = getchar();
然而,下面这条语句的意思是“从fp指定的文件中获取一个字符”:
ch = getc(fp);

与此类似,下面语句的意思是“把字符ch放入FILE指针fpout指定的文件
中”:

——《C Primer Plus 第六版(中文版)》

fopen()打开文件需要指定打开的模式:

在这里插入图片描述

写文件

利用putc()写文件貌似和读文件差不多;

void FileWriteTest()
{
    int i = 0;
    FILE* file_pointer;
    char TestString[] = "This is the test string; \
    \nIf you see this sentence in the test txt file, the file is written successfully.";

    file_pointer = fopen(TEST_FILE_PATH,"w");//打开文件

    //开始写入数据
    while(TestString[i]!='\0')
    {
        putc(TestString[i],file_pointer);
        i++;
    }
    fclose(file_pointer);//写入结束,关闭指定文件
    printf("\nEnd of file writing!\n");
}

其他读写函数

//fprintf()
int fprintf (FILE *__stream, const char *__format, ...);
/* 类似于printf()的格式化输出,不过可以指定让它输出到文件中 */
    
//fscanf()
int fscanf (FILE *, const char *, ...);
/* 从指定位置格式化输入,用法类似scanf() */
    
//fgets()
char * fgets (char *, int, FILE *);
/* 读取一行,并把它存储在 str 所指向的字符串内。
当读取到指定个(第二个参数)字符时,或者读取到换行符时,或者到达文件末尾时停止 */

//fputs()
int fputs (const char *, FILE *);
/* 将字符串输出到指定的流 */

//fseek()
int fseek(FILE *stream, long int offset, int whence);
/* 偏移文件指针(相对于whence) */
    
//ftell()
long int ftell(FILE *stream);
/* 读取偏移量(相对于whence) */
/*whence
SEEK_SET:文件开头
SEEK_CUR:指针当前位置
SEEK_END:文件结尾
*/

//......

注意

① 文件读写有字符模式和二进制模式;有一些区别,比如是否把Ctrl^Z\r\n当作字符的区别;这会导致ftell()等函数的工作不一样

② 如果ftell(),fseek()函数的long int不够用,还有fgetpos()fsetpos()函数也可以实现功能;

标准IO的流程

  • 首先,使用fopen()打开文件;并且创建缓冲区,创建文件信息结构体,返回指向该结构体的指针。关于缓冲区

  • 使用getc()等函数去读取字符时,文件数据(的一部分,如512byte或1Kb等等,取决于缓冲区大小和缓冲区模式等)被复制到缓冲区。

  • 当缓冲区中的数据读完之后,新的一部分文件数据被复制到缓冲区。

  • 以这种方式,输入函数可以读取文件中的所有内容,直到文件结尾。函数在读取缓冲区中的最后一个字符后,把
    结尾指示器设置为真。于是,下一次被调用的输入函数将返回EOF。

关于缓冲区的一个例子

#include <stdio.h>
#include <unistd.h>
#include <string.h>

int main()
{
 
   char buff[1024];//定义一个字符型数组作为缓冲区
 
   memset( buff, '\0', sizeof( buff ));//初始化缓冲区
   /*C库函数void *memset(void *str, int c, size_t n)可以
   复制字符 c(一个无符号字符)到参数 str 所指向的字符串的前 n 个字符。*/
 
   fprintf(stdout, "启用全缓冲\n");//将这句话输出到默认stdout缓冲区
   setvbuf(stdout, buff, _IOFBF, 1024);//定义stdout流,缓冲区设置为从buff开始,全缓冲,缓冲区大小1Kb
 
   fprintf(stdout, "这里是 runoob.com\n");//将这两句话输出到现在的stdout缓冲区
   fprintf(stdout, "该输出将保存到 buff\n");
   fflush( stdout );//刷新缓冲区,缓冲区中字符这时候才被输出到显示器(stdout)
 
   fprintf(stdout, "这将在编程时出现\n");//这两句话也被输出stdout缓冲区
   fprintf(stdout, "最后休眠五秒钟\n");//但是后面没有了刷新缓冲区的操作,并且缓冲区也没被填满
   //所以这两句话并不会输出到显示器上 
   sleep(5);
 
   return(0);
}
  • Debug过程;(多图预警

此时还没有执行memset( buff, '\0', sizeof( buff )),可以看到数组内部是垃圾数据。
在这里插入图片描述

初始化之后;
在这里插入图片描述

输出到默认缓冲区,显示器上没有输出,因为既没有刷新默认缓冲区,缓冲区也没被填满。

在这里插入图片描述

重新设置了stdout缓冲区之后,原来默认的缓冲区里的数据(“启用全缓冲”)被输出;

在这里插入图片描述
在这里插入图片描述

数据被输出到现在的缓冲区(buff);

在这里插入图片描述

刷新缓冲区之后,缓冲区数据被输出;
但是,缓冲区中的数据并没有被删除!!(终端显示的[New Thread xxx]请无视,偶然出现)

在这里插入图片描述
在这里插入图片描述

新的数据被写入时将原来的数据覆盖,还没被覆盖的数据依然还在!!

所以,可以知道fflush()函数并不会刷新缓冲区并不会删除缓冲区中的内容,只是像在一行字上再写一行字一样,只把笔尖重新定位到行首,而不划掉已经写了的字。

在这里插入图片描述

to be continued…

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

川九-EveRYouNg

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值