您的位置:首页 > 运维架构 > Linux

linux下的IO详解(fopen 和 open ,fread 和 read ,fwrite 和 write)

2019-03-27 13:36 183 查看

linux下的IO 函数经常使用(一),fopen 和 open

那么问题来了

  1. 上述的函数接口都代表什么意思?
  2. 函数开头带"f"的和不带"f"的有什么区别?
  3. 什么时候该用带"f"的什么时候该用不带"f"的?
    想必初学者经常会带着这几个疑问含含糊糊的在使用!OK,话不多说接下来我 们就围绕这三个问题展开讨论!
一 、每个函数代表什么意思? fopen:

linux使用shell命令行 man fopen

函数原型:

#include <stdio.h>
FILE *fopen(const char *path, const char *mode);

头文件:stdio.h,那就代表着此接口是标准C库函数

fopen的描述如下,

翻译过来是说(fopen函数打开名为path指向的字符串的文件,并将流与其关联。)

ok!
第一个参数很明显就是所打开的文件路径,没什么好说的。
第二个参数也是一个字符串 官方所给出的可选值如下:
"r": 打开一个文件并且标记为只读的,指针指向文件流的开始位置。
"r+":打开一个文件并且标记为可读可写的,指针指向文件流的开始位置。
"w":将文件截断为0长度,或者创建文件写入,指针指向文件流的开始位置。
"w+":打开用来读写操作的文件,如果该文件不存在则创建,如果存在则将文件截断为0长度,指针指向文件流的开始位置
"a":打开用来追加写入的文件,如果文件不存在则创建,指针指向文件流的末尾位置
"a+":打开一个用来读,或者追加写入的文件,如果文件不存在则创建,用来读操作指针指向文件流开头,用来写操作指针指向文件流末尾

返回值:FILE*
如果执行成功那么会返回一个指向文件流的指针,如果不成功可能返回NULL 或者 errno,这个全局的变量 可以通过 #include<string.h> 下的char *strerror(int errnum);来解析具体报错原因。

注意:errno必须立马获取查询,不然后续代码会重新覆盖errno
open:

linux使用shell命令行 man 2 open (请记住这里使用了man 2 这个指令而并没有使用man 指令,暂且先留下印象,后面会详细讲解原因)

函数原型:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);

open这里有俩个重载的函数具体描述如下,
Given a pathname for a file, open() returns a file descriptor, a small, nonnegative integer for use in subsequent system
calls (read(2), write(2), lseek(2), fcntl(2), etc.). The file descriptor returned by a successful call will be the low‐
est-numbered file descriptor not currently open for the process.
翻译过来是说( 给定文件的路径名,open()返回一个文件描述符,一个小的非负整数,供后续系统使用调用(read(2)、write、lseek、fcntl等)。成功调用返回的文件描述符)

ok!

第一个参数很明显就是所打开的文件路径,没什么好说的。
第二个参数也是一个字符串 官方所给出的常用(其余这里就不一 一介绍了,具体使用可以查看官方文档)可选值如下:
O_RDONLY: 只读打开
O_WRONLY: 只写打开
O_RDWR: 读,写打开
这三个常量,必须指定一个且只能指定一个
O_CREAT: 若文件不存在,则创建它,需要使用mode选项

S_IRWXU 00700 user (file owner) has read, write and execute permission

S_IRUSR  00400 user has read permission

S_IWUSR  00200 user has write permission

S_IXUSR  00100 user has execute permission

S_IRWXG  00070 group has read, write and execute permission

S_IRGRP  00040 group has read permission

S_IWGRP  00020 group has write permission

S_IXGRP  00010 group has execute permission

S_IRWXO  00007 others have read, write and execute permission

S_IROTH  00004 others have read permission

S_IWOTH  00002 others have write permission

S_IXOTH  00001 others have execute permission

)。来指明新文件的访问权限

O_APPEND:   追加写,如果文件已经有内容,这次打开文件所写的数据附加到文件的末尾而不覆盖原来的内容!

返回值:int flg
成功:返回一个int类型的文件描述符
失败:-1 查询具体失败原因使用,errno,这个全局的变量 可以通过 #include<string.h> 下的char *strerror(int errnum)
注意:errno必须立马获取查询,不然后续代码会重新覆盖errno

ok!

介绍完fopen 和 open,我们先不着急介绍后面write,fwrite,read,fread。篇幅太长不利于理解 所以 针对fopen 和 open的区别和使用放在下一章节

二、linux下fopen 和 open 区别

1. 来源:
fopen 来自标准I/O库(stdio)及其头文件stdio.h ,为底层I/O系统调用提供了一个通用的接口,其实ANSI标准C的一部分,配合使用的是fwrite,fread等。。后续文章会讲解!

open是glibc库函数(

glibc是Linux下使用的开源的标准C库,是GUN发布的libc库,及运行时库
),是linux对内核函数封装的系统调用函数,配合使用的是 write,read等。。后续文章会讲解!

移植性
这一点从上面的来源就可以推断出来,

fopen
是C标准函数,因此拥有良好的移植性;而
open
是linux系统调用,移植性有限。如windows下相似的功能使用API函数
CreateFile

适用范围
open返回文件描述符,而文件描述符是linux系统下的一个重要概念,linux下的一切设备都是以文件的形式操作。如网络套接字、硬件设备等。当然包括操作普通正规文件(Regular File)。
fopen是用来操纵普通正规文件(Regular File)的。

文件IO层次
如果从文件IO的角度来看,前者属于低级IO函数,后者属于高级IO函数。低级和高级的简单区分标准是:谁离系统内核更近。低级文件IO运行在内核态,高级文件IO运行在用户态。

缓冲
缓冲文件系统
缓冲文件系统的特点是:在内存开辟一个“缓冲区”,为程序中的每一个文件使用;当执行读文件的操作时,从磁盘文件将数据先读入内存“缓冲区”,装满后再从内存“缓冲区”依此读出需要的数据。执行写文件的操作时,先将数据写入内存“缓冲区”,待内存“缓冲区”装满后再写入文件。由此可以看出,内存“缓冲区”的大小,影响着实际操作外存的次数,内存“缓冲区”越大,则操作外存的次数就少,执行速度就快、效率高。一般来说,文件“缓冲区”的大小随机器 而定。fopen, fclose, fread, fwrite, fgetc, fgets, fputc, fputs, freopen, fseek, ftell, rewind等。
非缓冲文件系统
缓冲文件系统是借助文件结构体指针来对文件进行管理,通过文件指针来对文件进行访问,既可以读写字符、字符串、格式化数据,也可以读写二进制数据。非缓冲文件系统依赖于操作系统,通过操作系统的功能对文件进行读写,是系统级的输入输出,它不设文件结构体指针,只能读写二进制文件,但效率高、速度快,由于ANSI标准不再包括非缓冲文件系统,因此建议大家最好不要选择它。open, close, read, write, getc, getchar, putc, putchar等。

下一篇会讲解标准C库下的 fwrite, fread 和GLIBC库下的 write,read

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: