写下前面:
本篇博客主要介绍linux中的标准库的IO接口
fopen/fread/fwrite/fseek/fclose 文件打开/文件读取/文件写入/文件跳转/文件关闭
目录
- 文件访问方式
- fopen 文件打开接口
- fread 文件读取接口
- fwrite 文件写入接口
- fseek 文件跳转接口
- fclose 文件关闭接口
- fflush 刷新缓冲区
一、文件打开方式:
man fopen
r – 只读
r+ – 读写 读写打开文件,若文件不存在则报错
w --只写
w+ – 读写 读写打开文件,若不存在则创建,若存在将清空原有的内容
a – 追加写 每次写入数据总是写入到文件末尾 文件不存在就创建
a+ – 追加读写 文件不存在就创建
b – 二进制操作 默认清空如果不指定b 则认为文件是文本操作,加上b则认为是二进制操作;区别在于–有时候一个特殊的字符只是占据两个字节的内存
注意:读取一个100字节大小的文件、文本操作最终读取出来的数据、不一定是100个字节
二、fopen文件打开接口
函数:
FILE *fopen(const char *path, const char *mode); (文件路径,打开方式)
参数:
const char *path 文件路径 绝对路径/相对路径
const char *mode 文件访问方式
返回值:
示例:
#include<stdio.h>
int main()
{
FILE*fp=NULL;
fp=fopen("./txt.txt","r");
if(fp==NULL)//成功的话返回一个指向文件对象 不成功的话返回NULL 并且设置全局变量的值errno 来指示错误信息
{
perror("fopen error\n");//打印上一个系统调用接口使用错误原因
return -1;
}
else
{
printf("fopen success\n");
}
return 0;
}
这个时候我们是没有txt.txt 这个文件的,所以打开就会报错,显示没有这个文件。
当我们在该目录下建一个该文件时:
其实文件的打开方式也给我们提供了很大的便利,也可以在打开文件当文件不存在时可以自行进行创建,完成相应的场景的需要;
另外:注意 这里的路径应该是绝对路径或者相对路径,否则检测不到文件也会出现打开失败
当文件不存在 或者想在打开时,不存在可以新建一个 可以更改打开方式,例如:
fp=fopen("./txt.txt","a+");//追加写的方式 若文件不存在则新建一个文件 默认是在当前目录下新建
注意:“w+” 以读写方式打开文件,当文件存在时,会清空原有的文件中的所有内容。
三、fread 文件读取接口
一般常用的有这样两个:
函数:
1、size_t fread(char *buf,size_t block_size,size_t block_count,FILE * fp);(缓冲区,块大小,块个数,文件流指针)
2、size_t fread(char *data,size_t block_size,size_t block_count,FILE * fp);(数据首地址,块大小,块个数,文件流指针)
参数:
char *buf /char *data 都是一块空间的地址 是将读取的数据保存的位置
size_t block_size 块大小 按 块大小个字节进行数据读取 例如 char 的数据 按 1 个字节进行读取
size_t block_count 想要读取的块的个数
FILE *fp 文件流指针 想要读取的文件的指针
返回值:
成功时,fread()和fwrite()返回读取或写入的项目数(也就是读取了几个块大小为block_size的数据)。这个数字等于这个数字仅当传输的字节数大小为1时(也就是块大小为1 像char类型的数据)。
如果发生错误,或到达文件结尾,则返回值是短项目计数(或零)(比如你想访问10个块大小的数据,但是没有10块只有9块就返回 9 或者 想访问一块,但是数据不够一块大小则 返回 0)。
注意:例如读取整形的数字时 块大小为sizeof(int) ,块大小设置为4 若读取 10 个数字,当文件大小为36 时只能读取 9个数字 就会返回 9 ,当块大小为100 快个数为1 时 ,当文件大小不足100字节时 会返回0
#include<stdio.h>
int main()
{
int i=0;
int fp=0;
FILE*fp1=NULL;
fp1=fopen("./txt.txt","r");
char buf[1024];
fp=fread(buf,sizeof(char),10,fp1);//按照块大小进行读取,读取10个数据,比如字符文件块大小是 1 想要读取10 个 将读取到的文件写入到 buf中 返回值是 成功读取的块大小的个数
printf("%d \n",fp);
for(i=0;i<fp;i++)
{
printf("%c ",buf[i]);
}
return 0;
}
txt.txt 文件中的内容:
adkhadahhwgahwduwd
读取结果:
四、fwrite文件写入接口
函数:
size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);
(一块空间地址,块大小,快个数,文件流指针)
函数简介:
函数fwrite()将数据的nmemb元素(每个大小字节长)写入stream指向的流,从ptr指定的位置获取它们。也就是说将ptr中的块大小为size的nmemb个元素写入到文件流指针,写到文件中
参数:
参数与fread一样 不过一个是将数据读出来保存到一块空间,而fwrite是将一块空间中的数据写入到文件中;
返回值:
返回值和fread一样;
示例:
#include<stdio.h>
int main()
{
int i=0;
int fp=0;
int fp2;
FILE*fp1=NULL;
fp1=fopen("./txt.txt","a+");//追加读写的打开方式 文件不存咋则创建
char buf[1024];
fp=fread(buf,sizeof(char),10,fp1);
printf("读取的块个数(字符)为: %d个 \n",fp);
for(i=0;i<fp;i++)
{
printf("%c ",buf[i]);
}
printf("\n");
fp2=fwrite(buf,sizeof(char),5,fp1);
printf("成功写入的块个数为:%d个 \n",fp2);//查看成功写入的块个数 这里 一个char是一个块 即看写入几个字符
return 0;
}
再查看原本的文本中:
数据已经写入;
五、fseek文件跳转接口
函数:
int fseek(FILE *stream, long offset, int whence);
函数简介:为文件流指针指向的文件设置文件指示器的位置,比如读取的位置,文件写入的位置
介绍:
函数的作用是:为流指向的流设置文件位置指示器的新位置,以字节为单位,通过将偏移字节添加到whence指定的位置来获得。如果设置在哪里,可以设置为SET、SEEK U CUR或SEEK U END,分别是:偏移量相对于 文件的开始,当前位置,文件结尾。
成功调用fseek()函数将清除文件结尾指示流,并撤消ungetc(3)函数对同一流的任何影响。
参数:
FILE *stream 文件流指针 :需要对文件指示器位置设置的文件
long offset :偏移量 :相对于文件指示器的位置 单位字节 也可以是 负数 意思是向前偏移
int whence : 将读写位置设置为 [参数]的位置例如 文件开始 当前位置 文件末尾
SEEK_SET 将读写位置设置为文件开始
SEEK_CUR 将读写位置设置为当前文件指示器位置
SEEK_END 将读写位置设置为文件末尾
返回值:
成功后返回 0;否则返回 -1 并设置erron的错误信息
示例:
#include<stdio.h>
int main()
{
int i,j;
FILE*fp=NULL;
FILE*fp1=NULL;
FILE*fp2=NULL;
fp=fopen("./txt.txt","a+");
if(fp==0)
{
perror("fopen error\n");
}
else
{
printf("fopen success\n");
}
printf("写入的数据为: h e l l 0\n");
char buf[6]={'h','e','l','l','0'};
int temp=fwrite(buf,1,5,fp);//将buf 中的数据写入到 文件中
printf("写入的文件为 %d\n",temp);
fclose(fp);
fp1=fopen("./txt.txt","r");
char buf1[1024];
int set=fread(buf1,1,5,fp1);//读取文件中的 内容 到buf1中
printf("读取到文件中的内容为: %d块\n",set);
for(i=0;i<set;i++)
{
printf("%c ",buf1[i]);//对buf1中的数据打印查看
}
printf("\n");
fclose(fp1);
fp2=fopen("./txt.txt","r+");
int set3=fseek(fp2,2,SEEK_SET);//设置文件的读写位置 相对于文件的开始 偏移 2个字节 相当于在文件的开始位置的第二>个字节
if(set3==-1)
{
perror("fseek error\n");
}
if(set3==0)
{
printf("fseek success\n");
}
int set4=fwrite(buf,1,5,fp2);//将 buf中的数据再次写入到设置号文件位置指示器的文件中
printf("重新设置文件位置之后进行写入之后的文件数据:%d块 \n",set4);
fclose(fp2);
fp3=fopen("./txt.txt","r");
char buf2[1023];
int set5=fread(buf2,1,1023,fp3);
printf("重新写后入的数据为 %d 块\n",set5);
for(j=0;j<set5;j++)
{
printf("%c ",buf2[j]);
}
printf("\n");
fclose(fp3);//关闭文件
return 0;
}
这里是将其文件读写位置指示器偏移到了当对于文件开始的两个字节 因此,再次写入数据的时候,从第三个位置开始写或者读取数据。
六、fclose文件关闭接口
函数:
int fclose(FILE *stream);
参数:
FILE *stream 文件流指针
返回值:
注意:
关闭文件是为了防止资源泄露,而且也可以将缓冲区进行刷新,因为我们上述所做的将一个buf中的数据写入到一个文件中,其实是先写入到缓冲区,再由缓冲区写入到磁盘中文件的位置的,如果不刷新缓冲区是无法将缓冲区中的内容写入到磁盘中的,除了使用fclose关闭文件并刷新缓冲区,还可以使用fflush 来进行刷新缓冲区;
fflush 刷新缓冲区
示例:
#include<stdio.h>
int main()
{
int i;
FILE*fp=NULL;
fp=fopen("./testfflush.txt","a+");
char ptr[6]={'h','e','l','l','o'};
fwrite(ptr,1,6,fp);
//int temp=fflush(fp);//刷新之后才会写入到文件中 若不刷新 输入的数据还在缓冲区中
//文件中的数据并没有被写入
//if(temp==0)
//{
// printf("fflush success\n");
//}
//else
//{
// perror("fflush error\n");
//}
fp=fopen("./testfflush.txt","a+");
char ptr1[6];
int ret=fread(ptr1,1,5,fp);
printf("读取到写入的数据 %d 块 数据为:\n",ret);
for(i=0;i<ret;i++)
{
printf("%c ",ptr1[i]);
}
fclose(fp);
return 0;
}
示例:
使用 fflush刷新缓冲区之后:
刷新之后再次打开文件:
注意:
每次的读取文件的数据或者向文件中写入数据,都是先将数据加载到输入/输出缓冲区中,然后再对缓冲区中的数据进行读取,写入,最终输出到屏幕上,或者从输入缓冲区将数据写入到磁盘中的文件中。随然fclose 也可以刷新缓冲区,并保存文件,但是fflush可以实时的进行缓冲区的刷新,例如:将实时信息输出到终端。