Linux-文件IO

本文详细介绍了文件I/O操作的基本概念,包括文件描述符的作用、常见的文件I/O函数如open、read、write、lseek和close的使用方法,以及如何通过这些函数实现文件的打开、读取、写入、定位和关闭等操作。

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

所有执行 I/O 操作的系统调用(文件IO)都以文件描述符(fd),一个非负整数(通常是小整数),来指代打开的文件。文件描述符用以表示所有类型的已打开文件,包括管道(pipe)、FIFO、socket、终端、设备和普通文件。在程序开始运行之前,shell 代表程序打开这 3 个文件描述符(0,1,2)代表标准输入输出出错。

文件IO相关主要函数:open read write lseek close

1.打开操作:open系统调用既能打开一个业已存在的文件,也能创建并打开一个新文件。

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

|成功返回文件描述符,失败返回-1|
参数 flags 为位掩码,用于指定文件的访问模式,所列位掩码常量可进行逻辑或(|)操作,读写或者只读只写不能同时出现。mode 参数则指定了由 open()调用创建文件的访问权限,如果open()并未指定O_CREAT标志,则可以省略mode参数。
O_RDONLY:以只读方式打开文件
O_WRONLY:以只写方式打开文件
O_RDWR:以读写方式打开文件
O_CLOEXEC:设置 close-on-exec 标志
O_CREAT:若文件不存在则创建之  
O_DIRECT:无缓冲的输入/输出 
O_DIRECTORY:如果 pathname 不是目录,则失败  
O_EXCL:结合 O_CREAT 参数使用,专门用于创建文件  
O_LARGEFILE:在 32 位系统中使用此标志打开大文件 
O_NOATIME :调用 read()时,不修改文件最近访问时间
O_NOCTTY:不要让 pathname(所指向的终端设备)成为控制终端 
O_NOFOLLOW:对符号链接不予解引用
O_TRUNC:截断已有文件,使其长度为零 
O_APPEND:总在文件尾部追加数据  
O_ASYNC:当 I/O 操作可行时,产生信号(signal)通知进程 
O_DSYNC:提供同步的 I/O 数据完整性
O_NONBLOCK:以非阻塞方式打开  
O_SYNC:以同步方式写入文件  

2.读取操作:read系统调用从文件描述符 fd 所指代的打开文件中读取数据

#include<unistd.h>
sszie_t read(int fd,void*buffer,size_t count);

|读取成功返回读取的字节数(读取到EOF)返回0,失败返回-1|。
count 参数指定最多能读取的字节数-包括换行符。(size_t 数据类型属于无符号整数类型。)buffer 参数提供用来存放输入数据的内存缓冲区地址。缓冲区至少应有 count 个字节。一次 read()调用所读取的字节数可以小于请求的字节数。对于普通文件而言,这有可能是因为当前读取位置靠近文件尾部。当 read()应用于其他文件类型时,比如管道、FIFO、socket 或者终端,在不同环境下也会出现 read()调用读取的字节数小于请求字节数的情况。例如,默认情况下从终端读取字符,一遇到换行符(\n),read()调用就会结束。

3.写入操作:write()系统调用将数据写入一个已打开的文件中

#include<unistd.h>
sszie_t write(int fd,void*buffer,size_t count);

|成功返回写入的字节数,失败返回-1|。
write()调用的参数含义与read()调用相类似。buffer参数为要写入文件中数据的内存地址,count参数为欲从 buffer 写入文件的数据字节数,fd 参数为一文件描述符,指代数据要写入的文件。如果 write()调用成功,将返回实际写入文件的字节数,该返回值可能小于 count 参数值。这被称为“部分写”。对磁盘文件来说,造成“部分写”的原因可能是由于磁盘已满,或是因为进程资源对文件大小的限制。对磁盘文件执行 I/O 操作时,write()调用成功并不能保证数据已经写入磁盘。因为为了减少磁盘活动量和加快 write()系统调用,内核会缓存磁盘的 I/O 操作。

4.文件偏移量:文件偏移量是指执行下一个 read()或 write()操作的文件起始位置,会以相对于文件头部起始点的文件当前位置来表示。文件第一个字节的偏移量为 0。

#include<unistd.h>
off_t lseek(int fd,off_t offset,int whence)

|成功返回新的文件偏移量,失败返回-1|。
文件打开时,会将文件偏移量设置为指向文件开始,以后每次 read()或 write()调用将自动对其进行调整,以指向已读或已写数据后的下一字节。因此,连续的 read()和 write()调用将按顺序递进,对文件进行操作。针对文件描述符 fd 参数所指代的已打开文件,lseek()系统调用依照 offset 和 whence 参数值调整该文件的偏移量。offset 参数指定了一个以字节为单位的数值。
whence 参数则表明应参照哪个基点来解释 offset 参数:
SEEK_SET:将文件偏移量设置为从文件头部起始点开始的 offset 个字节。
SEEK_CUR:相对于当前文件偏移量,将文件偏移量调整 offset 个字节1 。
SEEK_END:将文件偏移量设置为起始于文件尾部的 offset 个字节。

5.关闭操作:close()系统调用关闭一个打开的文件描述符,并将其释放回调用进程,供该进程继续使用。当一进程终止时,将自动关闭其已打开的所有文件描述符。

#include<unistd.h>
int close(int fd);

|成功返回0,失败返回-1|。

实例:

#include<stdio.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>

int fd;
int err(char *err){
	printf("%s\n",err);
	close(fd);
	exit(0);
}
int main(int argc,char *argv[]){
	int num;int len;
	char buff[256];
	char *ss="------文本内容如下------";
	printf("%s\n",ss);
	system("cat 1.txt");printf("\n");
	
	num=read(0,buff,256);buff[num]='\0';
	printf("标准输入read-num=%d,read-buff:%s",num,buff);//标准输入可读取到换行符
	
	fd=open("1.txt",O_RDWR);
	if(fd== -1)err("open error");
	while((num=read(fd,buff,13))>0){
		buff[num]='\0';//防止最后一次读取缓冲区有其它数据-测试
		printf("read-num=%d,read-buff:%s\n",num,buff);
	};
	//if(num==0)exit(0);//后边写操作注释掉这行避免程序退出  0a1b2c3d4e5f
	if(num==-1)err("read error");
	num=write(fd,"test!",strlen("test!"));//继续用同个fd则尾部追加
	if(num==-1)err("write error");
	printf("write-num=%d\n",num);
	
	len=lseek(fd,0,SEEK_CUR);printf("SEEK_CUR:%d\n",len);//写操作完成--偏移量为文件大小
	len=lseek(fd,5,SEEK_SET);printf("SEEK_SET:%d\n",len);//--开头5偏移量
	len=lseek(fd,-5,SEEK_CUR);printf("SEEK_CUR:%d\n",len);//--开头0偏移量
        len=lseek(fd,-5,SEEK_END);printf("SEEK_END:%d\n",len);//写操作前的位置
	
	system("cat 1.txt");printf("\n");
	close(fd);
	
	return 0;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值