文章目录
前言
本文主要讲解了Linux下标准IO库函数,有:
fopen—fclose
feof—ferror—clearer
fflush
fseek—rewind—ftell
fgets—fputs
gets—puts
fprintf—printf—sprintf
fgetc—fputc
fread—fwrite
同时针对一部分函数提供了代码示例,便于学习
一、标准IO
fopen函数
FILE *fopen(const char *path,const char *mode);
返回值:struct_IO_FILE, 在/usr/include/libio.h可以查看其定义
这个结构体包含有:读写缓存的首地址,大小,位置指针等。
那么对于特殊的“文件”,路径有如下:
标准的输入流 stdin 0
标准的输出流 stdout 1
标准的出错流 stderr 2
对于mode来讲,有如下参数:
r或者rb | 打开只读文件,该文件必须存在 |
r+或者r+b | 打开可读写文件,该文件必须存在 |
w或者wb | 打开只写文件,若文件存在则文件长度清为0,即会擦些文件以前内容。若文件不存在则建立该文件 |
w+或者w+b或者wb+ | 打开可读写文件,若文件存在则文件长度清为0,即会擦除文件以前内容。若文件不存在则建立该文件 |
a或者ab | 以附加的方式打开只写文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被追加到文件尾,即文件原先的内容会被保留。 |
a+或者a+b或者ab+ | 以附加方式打开可读写的文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留。 |
其中:
b:二进制文件
r:只读方式打开文件,文件必须存在
w或者a:只写方式打开文件,文件不存在则创建。
区别:
w等价于“O_TRUNC”,是清除原来的内容
a等价于“O_APPEND”,是在原有内容上面加内容
(此处的O_TRUNC和O_APPEND是“open———IO函数“的参数)
+:读写方式打开文件,文件必须存在
要注意的是:fopen函数创建的文件权限是(0666)&(~umask)值
umask值可以用umask 0xxx 来修改
(0代表八进制,xxx代表任意三个八进制数)
Eg:创建一个文件
#include<stdio.h>
Int main(int argc,char *argv[])
{
FILE *fp;
fp=fopen(argv[1],w+);
if(fp==NULL);
{
printf(“creat file %s failure\n”,argv[1]);
return -1;
}
printf(“creat file %s success\n”,argv[1]);
fclose(fp);
return 0;
}
fclose函数
调用成功返回0,失败返回EOF,并且设置errno
在该文件被关闭之前,刷新缓存中的数据。如果标准I/O库已经为该流自动分配了一个缓存,则释放此缓存。
刷新缓存函数
fflush(FILE *fp)
把库函数中的缓存的内容强制写到内核中
文件位置指针函数
1.fseek()参数与lseek是一样的,但是返回值不一样
lseek的返回值是:当前文件的位置指针值
fseek的返回值是:成功返回0,失败返回-1
2.rewind(FILE* fp)用于设定流的文件位置指示为文件的开始,该函数调用成功无返回值
rewind()等价于(void)fseek(fp,0,SEEK_SET);
3.ftell(FILE* fp)用于取得当前的文件位置,调用成功则为当前文件位置指针,若出错则为-1
行缓存读写函数fgets和fputs
1.char fgets(char s,int size,FILE *stream)
第一个参数:缓存,即读到那里去
第二个参数:读多少字节
第三个参数:从什么地方读
返回值:若成功则为s(缓存的地址),若已处文件尾端或者出错则为NULL
2.int fputs(const char* s,FILE *stream)
第一个参数:缓存,即写什么内容
第二个参数:写到哪里去
返回值:若成功则为非负值,若出错则为EOF(一个宏定义,值为-1 )
#include<stdio.h>
Int main(int argc,char *argv[])
{
FILE *fp;
char buf[]=”hello linux”
char readbuf[128]={0};
fp=fopen(“./a.c”,”w+”);
if(fp==NULL)
{
printf(“open file a.c failure\n”);
return -1;
}
else
{
printf(“open file a.c success\n”);
}
fputs(buf,fp);
fseek(fp,0,SEEK_SET);
fgets(readbuf,128,fp);
printf(“readbuf:%s\n”,readbuf);
fclose(fp);
return 0;
}
行缓存读写函数gets和puts
char* gets(char* s)
int puts(const char *)
gets和fgets的区别:
1.gets()时不能指定缓存的长度,这样就可能造成缓存越界(如若该行长度长于缓存长度),写到缓存之后的存储空间中,从而产生不可预测的后果
2.gets()只能从标准输入中读
3.gets()与fputs()的另一个区别是:gets()并不将换行符存入缓存中,fgets将换行符存入缓存中。
puts与fputs的区别:
1.puts()只能向标准输出中写
2.puts和fputs的另一个区别是:puts输出时会添加一个换行符,fputs不会添加
打印函数
1.Int fprintf(FILE* fp,”字符串格式”);
fprintf可以输出到文件中,也可输出到显示器
printf只能输出到显示器
2.int sprint(char *str,”字符串格式”)
输出内容到字符串中
一个字符的读写函数fgetc和fputc
int fgetc(FILE* fp)
功能:从文件流读取一个字符
参数:文件流
返回值:正确为读取的字符,到文件结尾或者出错时返回EOF
int fputc(int c, FILE* fp)
功能:写一个字符到文件中
参数:第一个参数为要写的字符,第二个参数为文件流
返回值:成功返回输入的字符,出错返回EOF
注意:
fputc里面是有缓存的,但是不是行缓存函数。
两个函数的读写对象都是int类型的数据,不是char
文件判断函数
int feof(FILE* fp)
功能:判断是否已经到达文件结束
参数:文件流
返回值:到文件结束,返回为非0,不是则返回0
int ferror(FILE* fp)
功能:判断是否读写错误
参数:文件流
返回值:是读写错误,返回为非0,不是则返回0
void clearer(FILE *fp)
功能:清除流错误
参数:文件流
全缓存fread和fwrite函数
size_t fread(void* ptr,size_t size,size_t nmemb,FILE* fp);
size_t fwrite(const void ptr,size_t size,size_t nmemb,FILE fp);
功能:全缓存的读写函数
第一个参数(char*)ptr:读的存放点/写的内容
第二个参数:(size_t)size:每个读写单元内容的字节数
第三个参数:(size_t)nmemb:读写内容有多少个单元
第四个参数:(FILE*)fp:读写文件流
读写总字节:size*nmemb
返回值:实际读写的单元数(注意是单元数)
二、Linux中简易cat命令的实现
#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
#include<string.h>
Int main(int argc,char* argv[])
{
FILE* src_fp;
int read_ret;
if(argc<2)
{
printf(“please input src file\n”);
return -1;
}
src_fp=fopen(argv[1],”r”);
if(src_fp==NULL)
{
printf(“open src file %s failure\n”,argv[1]);
return -2;
}
printf(“open src file %s success\n”,argv[1]);
while(1);
{
read_ret=fgetc(src_fp);
If(feof(src_fp))
{
//printf(“read file %s end\n”,argv[1]);
break;
}
fputc(read_ret,stdout);
}
fclose(fp);
return 0;
}
总结
标准IO库函数一般要比文件IO库函数的效率高,因为标准IO库函数有缓存空间,与内核空间交换次数少,效率要更高。
链接: Linux的IO接口函数(一)
链接: 标准IO与文件IO