文件IO的分层设计
先看图:
malloc的buf对应application buffer,用户空间;
fwrite是系统提供的最上层接口,也是最常用的接口。它在用户进程空间开辟一个CLib buffer,将多次小数据量相邻写 *** 作(application buffer)先缓存起来,合并,最终调用write函数一次性写入(或者将大块数据分解多次write调用);
write函数通过调用系统调用接口,将数据从应用层copy到内核层,所以write会触发内核态/用户态切换。当数据到达page cache后,内核并不会立即把数据往下传递。而是返回用户空间。数据什么时候写入硬盘,有内核IO调度决定,所以write是一个异步调用
read调用是先检查page cache里面是否有数据,如果有,就取出来返回用户,如果没有,就同步传递下去并等待有数据,再返回用户,所以read是一个同步过程;
fclose隐含fflush函数,fflush只负责把数据从Clibbuffer拷贝到pagecache中返回,并没有刷新到磁盘上,刷新到磁盘上可以使用fsync函数;
即便fsync仍有可能没写到磁盘上,一是磁盘有缓存,二是即便关闭缓存也可能为了跑分没有真正关闭;
** 一致性
fwrite使用用户进程私有空间,多线程必然需要做同步。write如果写大小小于PIPE_BUF,是原子 *** 作。根据已知信息,内核所做仅限于此,如果两个进程同时写文件,可能出现错乱,需要实测。
** 安全性
从前面的分层设计来看,使用fsync函数可以最大限度保障安全写入,但仍然没有绝对的安全性。
另外一张图
打开一个读文件和一个写文件,用一个循环,fgetc每读一个字符,就用fputc写入另一个文件,这样就实现了文件的复制,和普通的C语言标准库编程是一样的,代码如下:int c
FILE *in, *out
in = fopen("file.in", "r")
out = fopen("file.out", "w")
while( ( c = fgetc(in) ) != EOF)
fputc(c, out)
fclose(in)
fclose(out)
Linux下C语言的文件(fputc,fgetc,fwrite,fread对文件读写 *** 作)
//
fputc 向文件写入字符
#include <stdio.h>
#include <stdlib.h>
main()
{
FILE *fp
char ch
if((fp=fopen("test.txt","w"))==NULL)
{
printf("不能打开文件\n")
exit(0)
}
while ((ch=getchar())!='\n')
fputc( ch, fp )
fclose(fp)
}
-------------
小提示:
fp=fopen("test.txt","w") ,把"w"改为 "a" 可以创建文件并且追加写入内容
exit(0)需要包含 stdlib.h 头文件,才能使用
//
fgetc 读取字符
#include <stdio.h>
#include <stdlib.h>
main( int argc, char *argv[] )
{
char ch
FILE *fp
int i
if((fp=fopen(argv[1],"r"))==NULL)
{
printf("不能打开文件\n")
exit(0)
}
while ((ch=fgetc(fp))!=EOF)
putchar(ch)
fclose(fp)
}
文件结尾,通过判断 EOF
//
fwrite 的使用
使数组或结构体等类型可以进行一次性读写
#include <stdio.h>
#include <stdlib.h>
main()
{
FILE *fp1
int i
struct student{
char name[10]
int age
float score[2]
char addr[15]
}stu
if((fp1=fopen("test.txt","wb"))==NULL)
{
printf("不能打开文件")
exit(0)
}
printf("请输入信息,姓名 年龄 分数1 分数2 地址:\n")
for( i=0i<2i++)
{
scanf("%s %d %f %f %s",stu.name,&stu.age,&stu.score[0],&stu.score[1], stu.addr)
fwrite(&stu,sizeof(stu),1,fp1)
}
fclose(fp1)
}
//
fread 的使用
#include <stdio.h>
#include <stdlib.h>
main()
{
FILE *fp1
int i
struct student{
char name[10]
int age
float score[2]
char addr[15]
}stu
if((fp1=fopen("test.txt","rb"))==NULL)
{
printf("不能打开文件")
exit(0)
}
printf("读取文件的内容如下:\n")
for (i=0i<2i++)
{
fread(&stu,sizeof(stu),1,fp1)
printf("%s %d %7.2f %7.2f %s\n",stu.name,stu.age,stu.score[0],stu.score[1],stu.addr)
}
fclose(fp1)
}
//
fprintf , fscanf, putw , getw , rewind , fseek 函数
这些函数的话我就不演示了 ,
这些函数基本都一对来使用,例如 fputc 和 fgetc 一起来用.
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)