标准IO函数
缓冲区
- 只有标准IO才有缓冲区,所有的数据都先放在缓冲区中,缓冲区满或者满足一定条件后刷新缓冲区
- 在实际生活生产过程中,代码会运行在死循环中,导致缓冲区可能不满且程序没有退出,所以必须要掌握缓冲区的刷新条件
全缓冲
- 操作对象:手动用fopenn函数打开文件后,创建的缓冲区都是全缓冲。用FILE *类型流指针进行维护。
- 大小:4096bytes = 4k
- 计算大小的代码:
fputc('a', fp);
printf("%ld\n", fp->_IO_buf_end - fp->_IO_buf_base );
- 刷新条件:
(1)缓冲区满(需要再向缓冲区中多写入一个之后才能将之前的4096个刷新出来)
(2)fflush函数,强制刷新输出流缓冲区
#include <stdio.h>
int fflush(FILE *stream);
(3)关闭流指针 (fclose)
(4)主函数调用return
(5)调用exit函数退出程序
(6)输入输出转换
行缓冲
- 操作对象:标准输入流指针(FILE *stdin)标准输出流指针(FILE *stdout)
- 大小:1024bytes = 1k
printf("size=%ld\n", stdout->_IO_buf_end - stdout->_IO_buf_base)
- 刷新条件
(1)缓冲区满(要多写一个后才能刷新前1024个)
(2)fflush函数,强制刷新输出流缓冲区
(3)关闭流指针 fclose
(4)主函数调用return
(5)调用exit函数退出程序
(6)遇到\n字符
(7)输入输出转换
无缓冲
- 操作对象:标准错误输出流指针(FILE *stderr)->perror函数默认封装就是stderr流指针
- 大小:1bytes,且只要往里存放数据,就会直接将数据刷新出来
- 无刷新条件
fputs
-
功能:将字符串输出到指定的文件中,fputs不会自动补充\n
-
原型:int fputs(const char *s, FILE *stream)
-
参数:char *s:指定要输出的字符串首地址
FILE *stream:流指针 -
返回值:成功返回非负数>=0;失败返回EOF;
fgets
-
功能:从指定文件中获取字符串
(1)最多获取size-1个字节,因为fgets函数在停止读取后,自动在有效字符的最后一个字节补上\0
(2)会获取空格和 \n 字符
(3)遇到 \n 字符后停止读取,且会获取 \n 字符 -
原型:char *fgets(char *s, int size, FILE *stream)
-
参数:char *s:存储获取到的字符串
int size:size - 1
FILE *stream:流指针 -
返回值:成功返回存储数据空间的首地址;失败返回NULL;当读取到文件结尾,且没有任何数据被读取出来,返回NULL
fwrite
-
功能:将数据的二进制形式写入到指定的文件中
二进制形式->将数据拆分成一个一个的字节并转换成字符形式写入文件中 -
原型:size_t fwrite(const void *ptr, size_t size, size_t nmemb,
FILE *stream) -
参数:void *ptr:指定要输出的数据的首地址;(void *类型,代表任意数据类型)
size_t size:每个数据所占的字节数大小
sizei_t nmemb:指定要输出的数据个数:注意是个数,不是字节数
FILE *stream:流指针 -
返回值:成功返回成功输出的数据个数,即nememb;失败时=0或者<nmemb
fread
-
功能:将数据的二进制形式从指定文件中读取出来,转换成对应的数据
-
原型:size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
-
参数:void ptr:指定要将数据存储到位置的首地址(void类型)
size_t size:每个数据所占的字节数大小
size_t nmemb:指定要读取的数据个数
FILE *stream:流指针 -
返回值:成功返回成功读取的数据个数:即nmemb;失败或者读取到文件结尾的时候,=0或者<nmemb
fseek
- 功能:修改文件偏移量到指定位置
- 原型:int fseek(FILE *stream, long offset, int whence)
- 参数:FILE *stream:指定要修改哪个文件的偏移量
long offset:距离whence参数指定的偏移量(往前便宜填负数,往后偏移填正数)
int whence:
SEEK_SET,文件开头位置
SEEK_CUR,文件当前位置
SEEK_END,文件结尾位置 - 返回值:成功返回0,失败返回-1,更新errno
- 注意:
1>若偏移量在文件开头,不能继续往前偏移
2>若偏移量在文件结尾,可以继续往后偏移
3>若是以w w+ r+的方式打开,往结尾后偏移10个字节后写入,则会从第10个字节写入数据,且前面空余部分会自动补充^@
4>若是以a a+方式打开,往后偏移10个字节后写入,从文件结尾的最后一个有效字符的后面写入。
ftell
- 功能:获取文件当前位置距离文件开头的偏移量
- 原型:long ftell(FILE *stream)
- 返回值:成功返回当前位置距离文件开头的偏移量;失败返回-1,更新errno
- 将文件偏移量修改到结尾,获取文件偏移量的值,就是文件大小
fseek(fp, 0, SEEK_END);
long size = ftell(fp);
练习:
一、使用fgets实现计算一个文件有几行
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <head.h>
int main(int argc, const char *argv[])
{
FILE *fp_r=fopen("./1.txt","r");
FILE *fp_w=fopen("./2.txt","w");
if(NULL == fp_r)
{
ERRO_MES("fopen");
return -1;
}
if(NULL == fp_w)
{
ERRO_MES("fopen");
return -1;
}
char str[20]="";
int count=0,line=0;
while(1)
{
if(NULL == fgets(str,sizeof(str),fp_r))
break;
line++;
fputs(str,fp_w);
count+=strlen(str);
}
printf("一共有%d个字节 有%d行\n",count,line);
fclose(fp_r);
fclose(fp_w);
fp_r=fp_w=NULL;
return 0;
}
二、用fread和fwrite实现文件拷贝
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
FILE *fp_r=fopen("read.txt","r");
if(NULL == fp_r)
{
perror("fopen");
return -1;
}
FILE *fp_w=fopen("write.txt","w+");
if(NULL == fp_w)
{
perror("fopen");
return -1;
}
char str[42]="";
while(1)
{
size_t num=fread(str,sizeof(str)-1,1,fp_r);
if(0 == num)
break;
fwrite(str,sizeof(str)-1,1,fp_w);
}
return 0;
}
三、思维导图