C语言文件IO

open

基于文件描述符的文件打开方式

  • 函数原型

#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);
int creat(const char* pathname,mode_t mode);
  • 参数

如果文件打开失败, open 将返回 -1 ,程序需要对异常情况进行处理。导致打开文件的原因又很多,例如:文件不存在;抑或权限不足等等。

  • flags

flags字段使用POSIX的几个宏,此时必须包含头文件<fcntl.h>才行。
可以是下面几个宏的逻辑或组合。这些宏共有三种类型:

访问方式描述
O_RDONLY只读
O_WRONLY只写
O_RDWR可读写
打开时标志描述
O_CREAT创建文件,需要指定第3个参数mode
O_EXCLO_CREAT联用,如果文件已存在则返回错误
O_TRUNC将清空文件的内容,仅对普通文件有用
O_NOCTTY若打开的文件是终端设备,不让它作为该进程的控制终端
O_NOBLOCK以非阻塞模式打开
IO操作方式描述
O_APPEND把数据写到文件末尾
O_NONBLOCK对文件的read()/write(),当无立即可用输入(或输出不能立即写出)时能以EAGAIN错误状态标志立即返回
O_ASYNC(异步)此标志被设置,文件描述符有输入数据时会生成SIGIO信号
O_SYNC
O_DSYNC
O_RSYNC
  • mode_t

可以查看man 2 open

read

  • 函数原型

#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
  • 参数

参数描述
fd文件描述符
buf读取的数据存放在buf指针指向的缓冲区
count读取的字节数
  • 返回值

若果函数执行成功,返回读取的字节数,如果遇到EOF,则返回0。出错返回**-1**,并设置相应errno值。

  • 当我指定要读取100个字节的时候,在读完30个字节后,遇到了EOF,那么这时立即返回30,接下来继续执行read函数的时候返回0。
  • 从终端设备读,通常以行为单位,读到换行符就返回。
  • 当出错时(即返回-1),如果errno的值是EINTR,表示遇到调用信号而中断了读取,那么我们可以再次尝试read。

write

  • 函数原型

#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
  • 参数

参数同read函数

参数描述
fd文件描述符
buf读取的数据存放在buf指针指向的缓冲区
count读取的字节数
  • 返回值

如果函数调用成功,返回值为写入的字节数;否则返回值为**-1**,并设置相应的errno值。

lseek

  • 函数原型

#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
  • 参数

  • fd是文件描述符

  • offset是偏移量

  • whence是偏移量的基准位置。它的取值有三个

    • SEEK_SET: 开始位置
    • SEEK_CUR: 当前位置
    • SEEK_END: 末尾位置
  • fd的偏移量

在内核中对一个文件描述符(fd)的偏移量只维护一个值,也就是说你用读写方式打开一个文件,如果先用read读取了n个字符,紧接着用write写入了n个字符,那么后来写入的n个字符并不是从文件第一个字符位置开始的,而是从n+1个字符位置开始的。所以通常我们需要使用lseek来使fd的偏移量置于文件开始位置。

access

函数用来判断用户是否具有访问某个文件的权限(或判断某个文件是否存在)。

  • 函数原型

#include<unistd.h>
int access(const char *pathname,int mode)
  • 参数

pathname:是文件的路径名+文件名(例:/home/book/file.txt)

mode:以下参数可选

F_OK 值为0,判断文件是否存在

X_OK 值为1,判断对文件是可执行权限

W_OK 值为2,判断对文件是否有写权限

R_OK 值为4,判断对文件是否有读权限

注:后三种可以使用或“|”的方式,一起使用,如W_OK|R_OK

  • 返回值

若测试成功则返回0,否则返回-1

fcntl

  • 函数原型

#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */ );
  • 参数

参数可能有两个,也可能有三个,具体看第二个参数的取值。

  • fd: 文件描述符
  • cmd: 命令
  • arg: 命令的参数
常用cmdarg描述
F_DUPFD复制文件描述符
F_GETFD获取文件描述符标签
F_SETFD设置文件描述符标签
F_GETFL获取文件状态标签
F_SETFL设置文件状态标签
F_GETFLK获取文件锁
F_SETFLK设置文件锁
F_SETLKW类似F_SETLK,但等待完成
F_GETOWN获取收到SIGIO信号的进程或进程组ID
F_SETOWN设置接收SIGIO信号的进程或进程组ID

文件描述符标签

文件描述符标签(flags)是一个整型,它的每一个二进制为,表明一种标志。

复制的文件描述符,标签不会被复制,每个文件描述符有各自的标签

当前,只有一个标志FD_CLOEXEC,表明当执行exec()函数时,将关闭该文件描述符。默认情况下,此位是清除的,所以在执行exec()之后,之前的文件描述符会保留。

fcntf(fd,F_SETFD,FD_CLOEXEC);//设置c该标志,但是其他标志就消失了。
//良好的写法是:
int oldflags = fcntl(fd,F_GETFD);
oldflags |= FD_CLOEXEC;//设置该标志
fcntl(fd,F_SETFD,oldflags);
//如果要清除该标志
oldflags &= ~FD_CLOEXEC;
  • 文件状态标签

文件状态标签被所有复制的文件描述符共享。表明文件打开的属性,也就是open()的flags参数所指明的。
当判断一个文件的读写标志时,不能简单的通过**&操作来判断,因为文件的读写标志有三种状态,系统中并非设置了三个独立位来表示,实际上是用了两个位来表示的。所以最好使用O_ACCMODE**(0x3)来进行**&操作。
其他的标志可以直接用
&**来判断,如flags&O_APPEND

dup

复制文件描述符号

  • 函数原型

#include <unistd.h>
int dup(int oldfd);
int dup2(int oldfd, int newfd);
  • dup,dup2

dup参数是一个文件描述符,返回一个文件描述符,值是当前未使用的最小数字,指向的位置和参数相同。

dup2,可以自己指定要返回的文件描述的数值newfd,如果newfd是一个已经打开的文件描述符,则会将其关闭。

另外还有dup3(),不常用。

  • dup2,fcntl

dup2(fd,fd2);
//等价于
close(fd2);
fcntl(fd,F_DUPFD,fd2);

功能上可以等价于close()和fcntl()的组合,但是dup2是一个原子操作(关闭fd2,和复制fd不会被中断)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值