目录
概念
特点
缓冲区
全缓冲:与文件有关
行缓冲:与终端相关
不刷新
函数
打开文件
fopen
feropen
打印错误信息perror
关闭文件
close
读写操作
fgetc(读取单个字符)
fputc(写入单个字符)
fgets(读取一行)
fputs(写入一行)
二进制读写
fread
fwrite
判断是否到文件结尾
feof
判断文件是否出错
ferror
定位操作
rewind
fseek
ftell
对比命令
diff
在c库(c语言函数库)中定义的一组用于输入输出的函数(接口)。
注意:
ctags索引的使用:
刷新条件:
刷新条件:
没有缓冲区,标准错误
FILE *fopen(const char *path, const char *mode)
功能:打开文件
参数:
path:打开的文件
mode:打开的方式
r/rb:只读,当文件不存在时报错,文件流定位到文件开头
r+/r+b:可读可写,当文件不存在时报错,文件流定位到文件开头
w/wb:只写,文件不存在创建,存在清空
w+/w+b:可读可写,文件不存在创建,存在清空
a/ab:追加(在末尾写),文件不存在创建,存在追加,文件流定位到文件末尾
a+/a+b:读和追加,文件不存在创建,存在追加,读文件流定位到文件开头,写文件流定位到文件末尾
注:当a的方式打开文件时,写只能在末尾进行追加,定位操作是无法改变写的位置,但是可以改变读的位置
返回值:
成功:文件流
失败:NULL,并且会设置错误码
#include
int main(int argc, char const *argv[])
{
//打开文件
FILE *fp;
fp = fopen("./a.txt", "r");
if (fp == NULL)
{
perror("fopen err");
return -1;
}
printf("fopen success\n");
//2读写操作
// int ch = fgetc(fp);
// printf("%c\n", ch);//h
// fputc('a', fp);
// ch = fgetc(fp);//l
// printf("%c\n", ch);
// fputc('b', fp);
// ch = fgetc(fp);//0
// printf("%c\n", ch);
// ch = fgetc(fp);//
// printf("%c\n", ch);
// //检测读到文件末尾
// if(feof(fp))
// printf("end...\n");
// fputc('k', fp);
// if (ferror(fp))
// printf("err\n");
//终端
int ch = fgetc(stdin);
fputc(ch,stdout);
//关闭文件
fclose(fp);
return 0;
}
FILE * freopen(const char *pathname, const char *mode, FILE* fp)
功能:将指定的文件流重定向到打开的文件中
参数:path:文件路径
mode:打开文件的方式(同fopen)
fp:文件流指针
返回值:
成功:返回文件流指针
失败:NULL
#include
int main(int argc, char const *argv[])
{
printf("hello\n");
FILE *fp;
fp = freopen("a.txt", "w+", stdout);
if(NULL==fp)
{
perror("freopen err");
return -1;
}
printf("world\n");
freopen("/dev/tty","r+",stdout);
printf("nihao\n");
return 0;
}
void perror(const char *s);
功能:根据errno值打印对应的错误信息
参数: s:提示语句
返回值:空
int fclose(FILE* stream);
功能:关闭文件
参数:stream:文件流
格式:int fgetc(FILE * stream)
功能:从文件中读取一个字符
参数:stream:文件流
返回值:
成功:读到的字符
失败或读到文件末尾:EOF(-1)
#include
int main(int argc, char const *argv[])
{
//终端
// char buf[32];
// fgets(buf, 5, stdin);
// printf("buf:%s\n", buf);//hell
//文件
FILE *fp = fopen("./a.txt", "r+");
if (fp == NULL)
{
perror("fopen err");
return -1;
}
printf("fopen okk\n");
char buf[32];
fgets(buf, 32, fp);
//printf("buf:%s\n",buf);
//fputs(buf, stdout);
fputs(buf, fp);
return 0;
}
格式:int fputc(int c, FILE * stream)
功能:向文件中写入一个字符
参数:
c:要写的字符
stream:文件流
返回值:
成功:写的字符的ASCII
失败:EOF
格式:char * fgets(char *s, int size, FILE * stream);
功能:从文件中每次读取一行字符串
参数:
s:存放字符串的地址
size:一次读取的字符个数
stream:文件流
返回值:
成功:s的地址
失败或读到文件末尾:NULL
特性:
每次实际读取的字符个数为size-1个,会在末尾自动添加\0
每次读一行,遇到\n后不再继续,读下一行
格式:int fputs(const char *s, FILE * stream);
功能:向文件中写字符串
参数:
s:要写的内容
stream:文件流
返回值:
成功:非负整数
失败:EOF
格式:size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
功能:从文件流读取多个元素
参数:
ptr :用来存放读取元素
size :元素大小 sizeof(数据类型)
nmemb :读取元素的个数
stream :要读取的文件
返回值:
成功:读取的元素的个数;
读到文件尾: 0
失败: -1
#include
int main(int argc, char const *argv[])
{
FILE *fp = fopen("./a.txt", "w+");
if (NULL == fp)
{
perror("fopen err");
return -1;
}
printf("fopen ok\n");
//二进制读写
float arr[3] = {1.23, 4.56, 7.89};
//写arr到文件中
fwrite(arr, sizeof(float), 3, fp);
rewind(fp);//将文件指针定位到开始位置
float new[3] = {0};
//从文件中将数据读出来
fread(new, sizeof(float), 3, fp);
printf("%.2f %.2f %.2f\n",
new[0], new[1], new[2]);
fclose(fp);
return 0;
}
格式:size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
功能:按对象写
参数:
ptr :用来存放读取元素
size :元素大小 sizeof(数据类型)
nmemb :读取元素的个数
stream :要读取的文件
返回值:
成功:写的元素个数
失败 :-1
格式:int feof(FILE * stream);
功能:判断文件有没有到结尾
返回:到达文件末尾,返回非零值
格式:int ferror(FILE * stream);
功能:检测文件有没有出错
返回:文件出错,返回非零值
练习1:
用fgets fputs实现cat功能
注意:cat是查看文件名
#include
int main(int argc, char const *argv[])
{
//cat 功能
/*打开文件,循环读文件并输出到终端,
当读到文件末尾EOF,feof结束循环 */
if (argc != 2)
{
printf("please input %s ", argv[0]);
return -1;
}
//1.打开文件
FILE *fp = fopen(argv[1], "r");
if (NULL == fp)
{
perror("fopen err");
return -1;
}
printf("fopen success\n");
//2.循环读文件
int ch;
while (1)
{
ch = fgetc(fp);
// if (feof(fp))
// break;
if (ch == EOF)
break;
fputc(ch, stdout);
}
//关闭文件
fclose(fp);
return 0;
}
练习2:
用fgets计算文件行数 (wc -l 文件名)
#include
#include
#include
//打开文件,用循环按行读写,每读一行,num++,最后关闭文件;换行的标准是“\n”,判断“\n”的个数
int main(int argc, char const *argv[])
{
if(argc!=2)
{
printf("please input filename\n");
return -1;
}
FILE *fp=fopen(argv[1],"r");
if(NULL == fp)
{
perror("fp error");
return -1;
}
printf("fp success\n");
char arr[32];
int num=0;
while(fgets(arr,32,fp) != NULL)//可以直接用数组的大小,遇到“\n”或数组读满,就进行下一次循环
{
if(arr[strlen(arr)-1]=='\n')//strlen不计算"\0"
num++;
}
printf("%d %s\n",num,argv[1]);
fclose(fp);
return 0;
}
练习3:
用fread fwrite实现cp功能,复制一张图片
#include
#include
#include
//实现cp功能,將一张图片复制到另一个文件里面,打开两个文件,读源文件写到目标文件中,关闭文件
int main(int argc, char const *argv[])
{
if(argc!=3)//打开了三个文件
{
printf("please input filname\n");
return -1;
}
FILE *f=fopen(argv[1],"r");
FILE *fp=fopen(argv[2],"w+");
if(NULL == f)
{
perror("f error\n");
return -1;
}
if(NULL == fp)
{
perror("fp error\n");
return -1;
}
printf("fp success\n");
char arr[1024];
int x;
while (!feof(f))//用循环读图片,因为不知道图片的大小,为了防止图片没有复制成功
{
x=fread(arr,sizeof(char),1024,f);//fread的返回值是数组的长度,用x返回arr的最新长度,x为了防止图片复制的和原图片复制的不一样
fwrite(arr,sizeof(char),x,fp);//读的时候只读数组的长度
}
return 0;
}
void rewind(FILE *stream);
功能:将文件位置指针定位到起始位置
参数:stream:文件流
格式:int fseek(FILE *stream, long offset, int whence);
功能:文件的定位操作
参数:
stream:文件流
offset:偏移量:正数表示向后文件尾部偏移,负数表示向文件开头偏移
whence:相对位置:
SEEK_SET:相对于文件开头
SEEK_CUR:相对于文件当前位置
SEEK_END:相对于文件末尾
返回值:
成功:0
失败:-1
注:当打开文件的方式为a或a+时,fseek不起作用
#include
int main(int argc, char const *argv[])
{
FILE *fp = fopen("./a.txt", "w+");
if (fp == NULL)
{
perror("fopen err");
return -1;
}
printf("fopen success\n");
fputs("hello world\n", fp);
printf("%ld\n",ftell(fp));//12
//相对于结束位置向前偏移了3个字符,写了n
fseek(fp, -3, SEEK_END);
fputc('n', fp);
printf("%ld\n",ftell(fp));//10
//相对于开始位置向后偏移了2个字符,写了nihao
fseek(fp, 2, SEEK_SET);
fputs("nihao", fp);
printf("%ld\n",ftell(fp));//7
//相对于当前位置向前偏移了2个字符,读字符
fseek(fp, -2, SEEK_CUR);
printf("%c\n", fgetc(fp));
printf("%ld\n",ftell(fp));//6
fclose(fp);
return 0;
}
格式:long ftell(FILE *stream);
功能:获取当前的文件位置
参数:要检测的文件流
返回值:成功:当前的文件位置,出错:-1
格式:diff 文件名1 文件名2
功能:ddiff是Linux命令,iff以逐行的方式,比较文本文件1和2的异同处。如果指定要比较目录,则diff会比较目录中相同文件名的文件,但不会比较其中子目录。