Linux文件 1.6 — 非字符串写入文件;fopen 与 open 打开文件的区别所在

其实我们来看 write()和 read() 函数,会发现 第二个参数 本来是一个 void * buf ,是一个空指针,当我们定义一个
int * p ,read(fd,p,sizeof(int));
就会传入一个整数给文件,而我们读取的时候,也可以用 read(fd,p,sizeof(int));来读取整数
但是,为什么我们之前说Linux的文件皆字符呢? 因为当写入整形数后,vi file;你会发现出现的其实是乱码;

那么我们怎么写入一个结构体呢?
我们搞一个结构体出来:

头文件已原地去世

struct test{
	int a;
	char c;
}
int main(){
	struct test data = {100,'a'};
// 咋写? 想想嘛,显然 就像写 字符串一样,肯定要在缓冲区搞一个结构体来承接嘛 
	struct test pdata;
	fd = open("./file1",O_RDWR);
	int n_write = write(fd,&data,sizeof(struct test));lseek(fd,0,SEEK_SET);
	int n_read = read(fd,&pdata,sizeof(struct test));
	close(fd);
	return 0;
}
那么,如果是结构体数组呢?
显然:
#denfine N 3
struct test data[N] = {{100,a},{101,b},{103,c}}
显然嘛,也要新建一个结构体数组
struct test pdata[N];
然后
	int n_write = write(fd,&data,sizeof(struct test) * N);
	int n_read = read(fd,&pdata,sizeof(struct test) * N);
	   // 没意思,走了

好了,我们学了 Linux 里面的文件操作,但是,你是否记得在 谭浩强的 C 语言这本书中,也写到过对文件的操作:
fopen();
fclose();
二者是区别是什么?
详情参见

  1. 来源:
    open() 是 UNIX 系统调用函数(包括 Linux 等),返回的是文件描述符(fd),fd 是文件在文件描述符表里的索引;
    fopen() 是 ANSIC 标准中的C语言库函数,在不同系统中,调用不同的内核 API,其返回值是一个指向文件的指针;

  2. 移植性:
    因为 fopen() 是 C 的标准函数,所以有很好的移植性;因为 open 是在 UNIX 系统中调用,就像 windows 中的 CreatFile 一样,只能在 各自系统环境中调用,而C语言标准函数,则只需要搭建C语言环境;

  3. 适用范围
    open 返回文件描述符是 UNIX 的一个重要的概念,因为是在做 LINUX 环境下的开发,后面讲到的进程,进程间的通信用到的管道,管道也是个文件,这个时候我们必须要用 open() 来打开。因为是 Linux系统,所以在一些特定的情况下,必须用 open打开。比如说:做硬件设备驱动,驱动是基于内核所写的代码,要有一定的移植性的限制,所以要使用 open();
    而 fopen 则可以用来操作 普通文件 (推荐普通文件使用 fopen )

  4. 文件的 IO 层次:
    如果从文件IO的角度来看,前者属于低级IO函数,后者属于高级IO函数。低级和高级的简单区分标准是:谁离系统内核更近。低级文件IO运行在内核态,高级文件IO运行在用户态。
    听不懂啊,你看哈,这张图,我们在 用户层(用户空间)调用函数,就是 “发送指令” 送达内核,而 fopen() 相对于 open() 而言,更多的操作是在用户空间,在自己的缓冲区里工作,对内核的依赖较小,而open() 则更多的使用内核。可以理解吧,fopen() 是C 标准库的,要兼容各种系统,而 open() 直接就是 UNIX 系统中的,自然更底层;
    在这里插入图片描述

  5. 缓冲

    1. 缓冲文件系统:
      缓冲文件系统的特点是:在内存中开辟一个 “缓冲区” ,为程序中每一个文件使用;当执行写文件操作时,先将数据写入内存 “缓冲区”,待内存缓冲区装满后,再写入文件;故而,内存缓冲区的大小,将影响实际操作中外存的次数,内存 “缓冲区” 越大,则操作外存的次数就越少,执行速度就越快,效率越高;文件 “缓冲区” 的大小将随机器而定;
      eg : fopen ; fclose ; fwrite ; fread ; fgetc ; fgets ; fputs ; fputc ;等

    2. 非缓冲文件系统:
      缓冲文件系统是借助文件结构体指针来对文件进行管理,通过文件指针来对文件进行访问,既可以读写字符、字符串、格式化数据,也可以读写二进制数据。非缓冲文件系统依赖于操作系统,通过操作系统的功能对文件进行读写,是系统级的输入输出,它不设文件结构体指针,只能读写二进制文件,但效率高、速度快,由于ANSI标准不再包括非缓冲文件系统,因此建议大家最好不要选择它。open ; close ; read ; write ; getc ; getchar ; putc ; putchar 等。

    一句话总结一下,就是open无缓冲,fopen有缓冲。前者与read, write等配合使用, 后者与fread,fwrite等配合使用。

    使用fopen函数,由于在用户态下就有了缓冲,因此进行文件读写操作的时候就减少了用户态和内核态的切换(切换到内核态调用还是需要调用系统调用API:read,write);而使用open函数,在文件读写时则每次都需要进行内核态和用户态的切换;表现为,如果顺序访问文件,fopen系列的函数要比直接调用open系列的函数快;如果随机访问文件则相反。

这样一总结梳理,相信大家对于两个函数及系列函数有了一个更全面清晰的认识,也应该知道在什么场合下使用什么样的函数更合适,效率更高。
(这只是理论上讲,事实上,在当今硬件条件越来越好的情况下,二者之间的差距越来越小了)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值