Linux文件IO操作/open/write/read函数的使用

open函数的使用示例

利用open函数打开一个文件,并验证下是否能无限次打开文件

//openfile.c

#include <stdio.h>      //C语言标准IO头文件,如调用printf()函数

#include <sys/types.h>  //调用open()函数所需的头文件
#include <sys/stat.h>
#include <fcntl.h>

int main()
{
	int fd;    //定义一个变量fd,存放文件描述符
	int i=1;   //定义一个变量i,用来记录打开文件的次数
	while(1)
	{
		fd = open("home/chenhai/test/main.c",O_RDWR);  //打开main.c文件,以读写方式打开;在while循环中,连续的打开该文件
		if(fd == -1)
		{
			printf("fail to open the file\n");  //如果文件描述符的值为-1,则打开文件失败
			break;
		}
		else
		{
			printf("fd=%d,",fd);
			printf("open main.c success %d\n",i++);
		}

    }
	
}

编译openfile.c程序并执行,按照程序逻辑,只要变量fd的值不为-1,就会陷入死循环一直打印

chenhai@linux:~/test$ gcc openfile.c -o demo
chenhai@linux:~/test$ ./demo

执行结果如下,可以看到,程序打印了1021次之后便退出了while循环,可见不能无限次打开文件main.c
在这里插入图片描述

通过Linux系统上的man手册,查看open函数的原型

chenhai@linux:~/test$ man 2 open   //open函数属于内核提供的功能函数,所以在man手册的第2页

man手册是一个很好用的帮助文档,它分成9页:

页数内容
1Executable programs or shell commands 可执行程序或shell命令
2System calls (functions provided by the kernel) 系统调用(内核提供的功能)
3Library calls (functions within program libraries) 库调用(程序库中的函数)
4Special files (usually found in /dev) 个特殊文件(通常位于/ dev中)
5File formats and conventions eg /etc/passwd 文件格式和约定,例如/ etc / passwd
6Games
7Miscellaneous (including macro packages and conventions), e.g. man(7), groff(7) 杂项(包括宏包和惯例)
8System administration commands (usually only for root) 系统管理命令(通常仅用于root)
9Kernel routines [Non standard] 内核例程[非标准]

截取man手册中的open函数部分介绍进行分析,对于系统提供的IO接口函数,我们不用去深究它的实现原理,我们只要使用它就好,可以看到该函数open的返回值类型是int,参数有两个,char型的指针*pathname指向的是需要打开的文件路径名,int型的变量flags是打开文件的操作权限请求
在这里插入图片描述
对man手册中关于open()函数的接口规范,总结如下表
在这里插入图片描述

那么上面的程序运行结果中,fd的值是从3开始的,前面的0 1 2去哪了呢?我们都知道,在Linux系统中有句话,“一切皆文件”,我们则可以使用系统IO接口去访问Linux系统中的所有文件,当申请打开一个文件的时候,系统会分配一个文件描述符给你,但是这个分配是有限度的,通过实验我们可以知道,打开文件的最大值为1023,其实就相当于去医院看病拿号一样,把医院当成一个系统,你去申请了排队看病,就分配了一个号码给你,当天的号码数量有限,分完即止,那每个人拿着这个号码(文件描述符),就可以去访问对应的医生(文件)了;之所以从3开始分配啊,是因为前面0-2都已经分配好了,0对应着标准输入设备文件(键盘),1对应着标准输出设备(屏幕),2标准出错设备(系统错误信息),所以啊这前面的三个号不能给你,你要申请只能从3开始

总结
每一个被打开的文件(键盘,显示器都是文件)都会有一个非负的描述符来对应他们;一个文件可以被重复打开多次,但不能无限次打开;每打开一次也都会有一个描述符对应,并且可以有不同的模式(文件操作权限);

write函数的使用示例

利用wirte函数,往一个空文本中写入数据

//创建一个空文本文件 
chenhai@linux:~/test$ touch a.txt

在这里插入图片描述

//编写程序,将字符串"hello"写入a.txt                 writefile.c
#include <stdio.h>

#include <sys/types.h>  //调用open()函数所需的头文件
#include <sys/stat.h>
#include <fcntl.h>

#include <unistd.h>     //调用wirte()函数所需的头文件

int main()
{	
	int fd;
	char buf[20]={"hello"};  //定义一个20字节大小的数组(数据缓冲区),用于存放要写入的数据

	//打开文件
	fd = open("/home/chenhai/test/a.txt",O_RDWR);  //读写方式打开,返回一个文件描述符,后面根据这个文件描述符对文件进行操作
	if(fd == -1)
	{
		printf("open a.txt faild\n");
	}
	else
	{
		
		printf("open a.txt ok\n");
	}

	//写入数据
	int ret = write(fd,buf,20);  //将数据从缓冲区中写入fd指向的文件,共写入20字节
	if(ret == -1)
	{
		
		printf("write a.txt faild\n");
	}
	else
	{	
		printf("write a.txt ok\n");
	}

	return 0;

}

在这里插入图片描述

那么,我们同样可以通过man手册来查看一下write的使用原理

chenhai@linux:~/test$ man 2 write

在这里插入图片描述

NAME
       write - write to a file descriptor
				 写入一个文件的描述符 
SYNOPSIS
       #include <unistd.h>
											
       ssize_t write(int fd, const void *buf, size_t count);
				参数一: 需要写入的设备 
				参数二: 需要写入的数据缓存区  
				参数三: 需要写入的数据大小  
				返回值:  成功  返回值写入的字节数  
				
						  失败  -1  错误 
								小于用户请求的字节数  写入失败
					

一般使用write 函数进行开发时,我们都是根据数据的真实大小写入。 

注意:使用write 函数的时候,他会根据用户的需求数据写入,假设 
	  真实数据不够,那么write 会自己补充一些乱码数据!!!!! 
	  
	  例子: 
	  char buf[1024]={"hello"};  //真实数据为5个字节  
	  write(fd,buf,1024);   	 //最后写入的是1024个字节, 1024 - 5 (个无效数据) 

read函数的使用示例

往一个文件写入数据,并读取数据

//readfile.c
#include <stdio.h>
#include <sys/types.h>  //调用open()函数所需的头文件
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>     //write  ,  read

int main()
{	
	int fd;
	char buf[10]={"hello"};
	char str[20]={0};

	//open file
	fd = open("/home/chenhai/test/a.txt",O_RDWR);
	if(fd == -1)
	{
		printf("open a.txt faild\n");
	}
	else
	{
		
		printf("open a.txt ok\n");
	}

	//write file
	int ret = write(fd,buf,10);
	if(ret == -1)
	{
		
		printf("write a.txt faild\n");
	}
	else
	{
	
		printf("write a.txt ok\n");
	}

#if 1

	close(fd);
	

	fd = open("/home/chenhai/test/a.txt",O_RDWR);
	if(fd == -1)
	{
		printf("open faild !!\n");	
	}
	else
	{
		printf("open success again\n");
	}

#endif

	int val = read(fd,str,20);
	if(val == -1)
	{
		printf("read faild!!!\n");
	}
	else
	{
		printf("read ok,the value is: %s\n",str);
	}

	return 0;

}

通过man手册查看read的使用方法
在这里插入图片描述

NAME
       read - read from a file descriptor
				读 从   文件描述符 
SYNOPSIS
       #include <unistd.h>

       ssize_t read(int fd, void *buf, size_t count);
			   参数一:需要读取的文件描述符  
			   参数二:读取后的数据缓存地址  
			   参数三:需要读取的数据大小
				返回值:   成功   返回读取到字节数  
						    0  	  已经读到文件的末尾了  
							-1    读取错误  

	

注意: 读函数,他只会根据文本中的内容去读取。  假设文本中只有10 个字节的数据,
	  用户要求读取100个字节的数据,那么最终只会读到   10个!!!   (因为它都没得给你读取啊。。。。。)

	  所以利用读取函数的时候,都是“越界"读取,要求读取的数据大小,要比文件中数据的真实大小要大!!!! 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值