栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

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

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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


C语言文件读写操作

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

文章目录
    • 读文件
    • 写文件
    • 其他读写函数
    • 注意
    • 标准IO的流程
    • 关于缓冲区的一个例子

读文件
  • 读文件
#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");
    
    
    //进入逐字符读取循环前首先判定文件是否为空文件(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]!='')
    {
        putc(TestString[i],file_pointer);
        i++;
    }
    fclose(file_pointer);//写入结束,关闭指定文件
    printf("nEnd of file writing!n");
}
其他读写函数
//fprintf()
int fprintf (FILE *__stream, const char *__format, ...);

    
//fscanf()
int fscanf (FILE *, const char *, ...);

    
//fgets()
char * fgets (char *, int, FILE *);


//fputs()
int fputs (const char *, FILE *);


//fseek()
int fseek(FILE *stream, long int offset, int whence);

    
//ftell()
long int ftell(FILE *stream);



//......
注意

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

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

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

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

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

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

关于缓冲区的一个例子
  • 代码来自菜鸟教程
#include 
#include 
#include 

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

此时还没有执行memset( buff, '', sizeof( buff )),可以看到数组内部是垃圾数据。

初始化之后;

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

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


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

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


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

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

to be continued…

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1033846.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号