一、标准IO - 按对象读写
下列函数用来从流中读写若干个对象:
#include <stdio.h>
size_t fread(void *ptr,size_t size ,size_t n,FILE *fp)
size_t fwrite(const void *ptr,size_t size ,size_t n,FILE *fp)
- 参数:ptr 读写缓冲区
size 读写对象的大小(int 类型4个字节 ,char 对象1个字节)
n 读写入对象的个数。
fp 需要读出,写入的文件
- 成功返回读写的对象个数,出错时返回EOF(-1)
- 如果文件中的对象个数小于指定的n时,读写完成后返回实际读写的对象个数。
- 如果读写到文件的最末尾,则返回0;
- 效率高
二、小结
- 按字符读写:fgetc/fputc 可操作文本文件以及二进制文件 效率低
- 按行读写 : fgets/fputs 不可操作二进制文件
- 按对象读写: fread/fwrite 即可操作文本文件,也可操作二进制文件 效率高
- 按对象读写 集中了前两种方式的所有优点,通常情况下使用第三种方式。
三、思考与练习
1、如何利用fread /fwrite 实现文件的复制?
#include <stdio.h>
int main(int argc, const char *argv[])
{
FILE *fp;
FILE *fpd;
int buff[20];
int ch;
if(argc<3) //判断一下输入的参数 是否小于三个
{
printf("Usage : %s <src_file><dst_file>\n",argv[0]);
return -1;
}
if((fp = fopen(argv[1],"r")) == NULL) // 以只读 方式打开必须存在的文件
{
perror("fopen src file ");
return -1 ;
}
if((fpd = fopen(argv[2],"w")) == NULL) //以只写 清空方式打开文件,不存在则 创建
{
perror("fopen dst file ");
return -1 ;
}
while((ch = fread(buff,1,1,fp)) != 0) // 从文件中读出数据放入 buffhu缓冲中
{
fwrite(buff,1,1,fpd); // 将buff缓冲中的 数据 写入 文件fpd中
}
fclose(fp); //关闭文件 fp
fclose(fpd); //关闭文件 fp
return 0;
}
2、通过fread返回值判断是否读到文件末尾?
— 当fread 返回 0 时 ,则说明 该文件读到了末尾。
四、标准io ----- 流的刷新(熟练)
流的刷新:将流的缓冲区的数据正式写入 流中。
- 标准IO中,先操作的是缓冲区,满足一定的条件后会自动刷新缓冲区。
1、缓冲区满时(全缓冲/行缓冲/遇到/n换行符),刷新流;
2、流关闭时,缓冲区会被刷新。
3、使用指定函数:
int fflush(FILE *pf);
- 成功时返回0;出错时返回EOF;
- 将流缓冲区中的数据写入实际的文件。
- Linux下只能刷新输出缓冲区。
#include <stdio.h>
int main(void)
{
FILE *fp;
if((pf = fopen(“test.ctxt”,”w”)) == NULL)
{
perror(“fopen”);
return -1;
}
fput(‘a’,fp);
fflush(fp);
while(1);
return 0;
}
五、标准IO ----- 流的定位(熟练)
ftell/fseek/rewind 函数 流的定位
- long ftell (FILE *stream);
- long fseek (FILE *stream,long offset,int whence);
参数含义:offset:偏移量 whence : 基准点(文件开始,相对当前位置,末尾)
- void rewend(FILE *stream);
- ftell() 成功返回时返回流的当前读写位置,出错时返回EOF.
- fseek() 定位一个流,成功时返回0;出错时返回EOF;
- whence 参数:SEEK_SET(文件开始)/SEEK_CUR(文件相对当前位置)/SEEK_END(文件末尾)
- offset 参数:偏移量,可正可负
- rewind() 将流定位到文件开始位置。
— 读写时,当前读写位置自动后移。
示例 : 获取文件长度。
if(fseek(fp,0,SEEK_END) == 0)
{
ch = ftell(fp);
if(ch != EOF)printf("%d \n",ch);
}
六、标准IO ---- 判断流是否出错或则结束。
#include <stidio.h>
int ferror(FILE *stream);
int feof (FILE *stream);
— ferror() 返回1表示流出错;否则返回0
— feof() 返回1表示文件已经到末尾;否则返回0
七、 标准IO --------- 格式化输出
1、标准IO ------- sprintf(熟练)
sprint(char *s,const char *fmt,…..):将需要输出的数据按照指定格式输出到存储空间s中。
2、标准IO ------- fprintf(熟练)
fprintf(FLIE *stream ,const char *fmt,…..):将需要输出的数据按照指定的格式输出到流中。
3、标准IO --------- printf(熟练);
printf(const char *fme,…….); :将需要输出的数据按照指定的格式输出到显示屏中。
— 成功时返回输出的字符个数;出错时返回EOF;
--- 使用起来很方便,强烈推荐。
4、小结
示例:以指定的格式“年-月-日”分别写入文件和缓冲区。
- time() :用来获取系统时间(秒数)获取的是从1970-01-01 00:00:00到本地时间的总秒数。
- localtime() : 将系统时间转换成本地时间。
- sleep() :实现程序睡眠。
- 以何种方式打开流。
- 流的缓冲类型对于文件写入的影响。
思考与练习:
每隔1秒向文件test.txt中写入当前系统时间,格式如下:
1,2019 -10 -18 10:01:21
2,2019 -10 -18 10:01:45
该程序无限循环,直到按Ctrl – C终端程序。
每次执行程序时,系统时间追加到文件末尾,序号递增。
1,2019 -10 -18 10:01:21
2,2019 -10 -18 10:01:45
3,2019 -10 -18 10:02:08
4,2019 -10 -18 10:02:36
#include <stdio.h>
#include <time.h> // time localtime
#include <string.h>
#include <unistd.h> //sleep
int main(int argc, const char *argv[])
{
FILE *fp;
time_t t;
struct tm *tp;
char buff[64];
int link = 0;
if(argc<2)
{
printf("Usage : %s <src_file><dst_file>\n",argv[0]);
return -1;
}
if((fp = fopen(argv[1],"a+")) == NULL)
{
perror("fopen src file ");
return -1 ;
}
while(fgets(buff,64,fp) != NULL)//判断文件有几行
{
if(buff[strlen(buff)-1] == '\n')link++;
}
while(1)
{
time(&t);
tp = localtime(&t);
fprintf(fp,"%02d,%d-%02d-%02d %02d:%02d:%02d \n",++link,tp->tm_year+1900,tp->tm_mon+1,tp->tm_mday,tp->tm_hour,tp->tm_min,tp->tm_sec);
fflush(fp);
sleep(1);
}
fclose(fp);
return 0;
}