Linux的文件I/O操作

本文介绍了文件I/O常用的函数,包括open、creat、close、read、write、fsync、lseek和ioctl函数。详细说明了各函数的功能、原型定义所在头文件、操作成功与失败的返回值,以及部分函数的参数含义,还提及了open与creat函数创建文件时的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

文件I/O常用头文件

#include <sys/types.h>    //定义数据类型,如ssize_t等
#include <fcntl.h>        //定义open,create等函数原型,创建文件权限的符号常量S_IRUSR等
#include <unistd.h>       //定义read,write,close,lseek等函数原型
#include <errno.h>        //与全局变量errno相关的定义
#include <sys/ioctl.h>    //定义ioctl函数原型

目录

一、open函数

二、creat函数

三、close函数

四、read函数

五、write函数

六、fsync函数

七、lseek函数

八、ioctl函数


一、open函数

1.进行文件I/O操作时,要先调用open()函数打开文件,它返回的文件描述符fd就代表了所打开的文件,后续的其他操作均通过引用该文件描述符fd进行。open()函数原型在<fcntl.h>中定义:

int open(const char *pathname, int flags, .../*mode_t mode*/);

2.1 open()参数

参数

打开文件标志

含义
pathname-C字符串形式的文件名
flagsO_RDONLY以只读方式打开文件,与O_WRONLY和O_RDWR互斥
O_WRONLY以只写方式打开文件,与O_RDONLY和O_RDWR互斥
O_RDWR以可读写方式打开文件,与O_WRONLY和O_RDONLY互斥
O_CREAT如果要打开的文件不存在,则创建该文件
O_EXCL该标志与 O_CREAT 共同使用时,会去检查文件是否存在,若文件不存在则创建该文件,否则将导致打开文件失败。此外,打开文件链接时,使用该标志将导致失败
O_NOCTTY如果要打开的文件为终端设备时,则不把终端设备当成进行控制终端
O_TRUNC若文件存在且以可写方式打开,此标志会清除文件内容,并将其长度置为0
O_APPEND读写文件都从文件的尾部开始,所写入的数据会以附加的方式加入到文件末尾
O_NONBLOCK以不可阻塞方式打开文件,也就是不管有无数据需要读写或者等待,都会立刻返回
O_SYNC以同步方式打开文件
O_NOFOLLOW如果文件名所指向的文件本身为符号链接,则会导致打开文件失败
O_DIRECTORY如果文件名所指向的文件本身并非目录,则会导致打开文件失败
mode-创建文件的权限模式,可以用八进制数来表示新文件的权限,也可采用<fcntl.h>中定义的符号常量。当打开已有文件时,将忽略这个参数

2.2 mode参数可用的符号常量表

符号常量含义符号常量含义
S_IRWXU0x700所属用户读、写和执行权限S_IRWXG0x070组用户读、写和执行权限
S_IRUSR0x400所属用户读权限S_IRGRP0x040

组用户读权限

S_IWUSR0x200所属用户写权限S_IWGRP0x020组用户写权限
S_IXUSR0x100所属用户执行权限S_IXGRP0x010组用户执行权限
S_IRWXO0x007其他用户读、写和执行权限S_IWOTH0x002其他用户写权限
S_IROTH0x004其他用户读权限S_IXOTH0x001其他用户执行权限

二、creat函数

1.open()函数的参数flags,当设置了O_CREAT标志时,可以创建一个新文件,也可以用另外一个函数creat()创建新文件,creat()函数原型在<fcntl.h>文件中定义:

int creat(const char *pathname, mode_t mode);    //参数pathname,mode同open

2.open与creat区别注意:

(1)creat()创建文件时,如果文件已存在,则会把已存在的文件内容清空、长度截为0,然后返回对应的文件描述符;如果文件不存在,则直接创建,然后返回文件描述符

   (2)   当open()的参数flags设置了O_CREAT时,如果文件已存在,则直接打开并返回文件描述符;如果文件不存在,则创建新文件,然后返回对应的文件描述符

 

三、close函数

1.文件I/O操作完成后,应该调用close()关闭打开的文件,释放打开文件时所占用的系统资源,close()函数原型在<unistd.h>中定义:

int close(int fd);    //fd为open()或creat()返回的文件描述符

四、read函数

1.从打开的文件读取数据,可调用read()函数实现,read()函数原型在<unistd.h>中定义:

ssize_t read(int fd, void *buf, size_t count);

操作成功,返回实际读取的字符数,如果已达到文件结尾,返回0,,否则返回-1

2.参数:

(1)fd:open()或creat()返回的文件描述符

(2)buf:用来接收所读数据的缓冲区

(3)count:请求读取的字节数,其中若文件长度小于请求的长度,则首次调用read时,返回文件长度,下次调用时返回0。读设备文件时,有些设备每读到一行数据,就返回

 

五、write函数

1.把数据写入文件,可调用write()函数实现,write()函数原型在<unistd.h>中定义:

ssize_t write(int fd, void *buf, size_t count);

操作成功,返回实际写入的字节数,出错则返回-1

2.参数:同read()

 

六、fsync函数

1.write()函数一旦返回,表明所写的数据已提交到系统内部缓存,但此时数据不一定写入了磁盘等持久存储设备中。要确保已修改过的数据全部写入持久设备中,正确的做法是调用fsync函数进行文件数据同步,强制把已修改的文件数据写入持久存储设备中。其原型在<unistd.h>中定义:

int fsync(int fd);

操作成功返回0,否则返回-1

七、lseek函数

1.Linux文件按读写方式可分为顺序读写和随机读写文件。普通磁盘文件一般都能随机读写,这类文件可通过lseek()函数改变文件读写位置。lseek()函数不会读写任何文件数据,仅仅是改变文件的起始读写位置。lseek()函数原型在<unistd.h>中定义:

off_t lseek(int fd, off_t offset, int whence);

如果操作成功,lseek()返回新的读写位置;否则返回-1

2.参数:

(1)offset:目标位置

(2)whence:偏移的参照点,有效值是SEEK_SET、SEEK_CUR、SEEK_END,含义如下:

          SEEK_SET:从文件开头算起

          SEEK_CUR:从当前所在的位置算起,偏移offset字节,正值表示往文件尾部偏移,负值表示往文件头部偏移

          SEEK_END:从文件结尾算起,正值表示往文件尾部偏移,负值表示往文件头部偏移

八、ioctl函数

1.文件I/O操作还有很多不好归到read()/write()的,只好放在这个函数中。很多设备文件用过ioctl()函数提供设备特有的操作,比如修改设备寄存器的值。ioctl()是文件i/o的杂项函数,其函数原型在<sys/ioctl.h>中定义:

int ioctl(int fd, int cmd, ...);

操作成功返回0;失败返回-1

2.参数

(1)cmd:文件的操作命令。该命令是文件专有的,不同的文件,cmd往往是不同的

(2)“...”:表示从参数是可选的、类型不确定的


示例代码:

#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/ioctl.h>

int main(int argc, char *argvp[])
{
	char buf[128] = { 0 };
	char w_str[] = "Hello,Linux file.\n";
	char filename[] = "hello.txt";
	int fd, rec;
	int mode = 0x664;
	int cur, newcur, offset = 0;

	fd = open(filename, O_RDWR|O_CREAT, mode);	//以可读写、创建标志打开文件,mode=0x664
	if (fd < 0)
	{
		printf("open file error.\n");
		return -1;
	}

	rec = read(fd, buf, sizeof(buf));	//读文件
	if (rec < 0)
		printf("read file error.\n");

	rec = write(fd, w_str, sizeof(w_str));	//写文件
	if (rec < 0)
		printf("write file error.\n");

	cur = lseek(fd, 0, SEEK_CUR);	//获取当前读写位置
	offset = 18 - cur;	//移动到偏移18个字节的位置读数据
	newcur = lseek(fd, offset, SEEK_CUR);	//从当前位置,移动到18
	if (newcur == -1)
		printf("lseek error.\n");
	
	fsync(fd);	//同步文件
	close(fd);	//关闭文件

	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值