linux系统I/O函数

linux系统I/O函数

  • linux系统I/O函数大体分两类:操作文件的和操作目录的
  • 查看man文档:man 2 函数名 //2 -第二章
    注意:调用系统函数注意返回值的判断对错误进行输出和形参的选择

文件

  • open()
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<stdio.h>
#include <unistd.h>
#include<stdlib.h>
int main()
{
	int fd;//保存open函数的返回值.
	/*******************************************************
	*函数: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);
	*1.打开已经存在的文件:fd=open("a.c",O_RDWR);
	*2.创建文件:fd=open("h.c",O_RDWR|O_CREAT,777);  
	*3.判断文件是否存在:fd=open("h.c",O_RDWR|O_CREAT|O_EXCL,777);  此时O_CREAT|O_EXCL必须联合使用
	*4.文件截断为0,清空文件:fd=open("a.c",O_RDWR|O_TRUNC);
	*返回值: open(), openat(), and creat() return the new file descriptor(fd:记录在内核区的pcb进程控制块里,唯一的), or -1  if
    * an error occurred (in which case, errno is set appropriately).
	********************************************************/
	//fd=open("a.c",O_RDWR);
	//fd=open("h.c",O_RDWR|O_CREAT,777);
	//fd=open("h.c",O_RDWR|O_CREAT|O_EXCL,777);
	fd=open("a.c",O_RDWR|O_TRUNC);
	printf("fd=%d\n",fd);
	//系统函数返回值很重要,对他进行判断,如返回-1则发生错误.
	if(fd==-1)
	{
		/*******************************************************
		*函数:perror()
		*头文件:#include<stdio.h>
		*作用:输出open()函数对应的错误值
		********************************************************/
		perror("open file");//调用perror函数,open file是我们自己定义的错误名字:输出错误描述
		exit(1);//退出进程,刷新缓存  头文件:#include<stdlib.h>
	}
	/*******************************************************
	*函数:close()
	*头文件: #include <unistd.h>
	*格式:int close(int fd);
	*返回值:close()  returns  zero on success.  On error, -1 is returned, and errno
    *is set appropriately.
	********************************************************/
	int ret=close(fd);//close函数需要传入fd值.
	printf("ret=%d\n",ret);
	return 0;
}
  • read()和write()
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<stdio.h>
#include <unistd.h>
#include<stdlib.h>
/*******************************************************
*
*使用read()和write()函数给文件test_open.c函数创建一个附件.
*
********************************************************/
int main2()
{
	
	//fd=open("a.c",O_RDWR);
	//fd=open("h.c",O_RDWR|O_CREAT,777);
	//fd=open("h.c",O_RDWR|O_CREAT|O_EXCL,777);
	//打开被读文件
	int fd=open("./test_open.c",O_RDWR);
	//系统函数返回值很重要,对他进行判断,如返回-1则发生错误.
	if(fd==-1)
	{
		perror("open file error");//调用perror函数,open file是我们自己定义的错误名字:输出错误描述
		exit(1);//退出进程,刷新缓存  头文件:#include<stdlib.h>
	}
	//创建一个新的文件副本
	int fd1=open("./test_open.c(附件)",O_RDWR|O_CREAT,777);
	if(fd1==-1)
	{
		perror("creat file error");
		exit(1);
	}
	//读文件
	/*******************************************************
	*函数:read() 
	*头文件:#include <unistd.h>
	*格式: ssize_t read(int fd, void *buf, size_t count); //fd:文件描述符-需要读取的文件;buf:读文件的buf;count:buf的大小(sizeof(buf))
	*返回值:0-成功;-1-失败; >0:已经读取的大小.
	********************************************************/
	char buf[2048];
	int count=read(fd,buf,sizeof(buf));
	if(count==-1)
	{
		perror("read file error");
		exit(1);
	}
	while(count) //只要count不返回0就表示读取没有完成;
	{
		//写文件
		/*******************************************************
		*函数:write() 
		*头文件:#include <unistd.h>
		*格式: ssize_t write(int fd, const void *buf, size_t count); //fd:文件描述符-被写入的文件;buf:存储的需要写入的数据;count:buf的大小(sizeof(buf))
		*返回值:0-成功;-1-失败; >0:已经写入的大小.
		********************************************************/
		int count1=write(fd1,buf,sizeof(buf));
		if(count1==-1)
		{
			perror("write file error");
			exit(1);
		}
		count=read(fd,buf,sizeof(buf));
		if(count==-1)
		{
			perror("read file error");
			exit(1);
		}
		
	}
	//关闭文件
	close(fd);
	close(fd1);
	return 0;
}
  • lseek()
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<stdio.h>
#include <unistd.h>
#include<stdlib.h>


int main()
{
	int fd=open("./b.c",O_RDWR);
	if(fd==-1)
	{
		perror("open file error");
		exit(1);
	}
	/*******************************************************
	*函数:lseek() 
	*头文件:  #include <sys/types.h>  #include <unistd.h>
	*格式:off_t lseek(int fd, off_t offset, int whence);  //offset:偏移量; whence:三个SEEK_SET(设置文件指针在offset的位置)、SEEK_CUR(设置偏移量从当前文件文件指针开始eg:当前位置为2,offset=3,所以指针位置为5)、SEEK_END(偏移量从结尾开始)可选
	*1.移动文件指针
	*2.查看文件大小:ret=lseek(fd,2000,SEEK_END)					//返回值就是文件的大小
	*3.拓展文件大小(只能向后拓展):ret =lseek(fd,2000,SEEK_END) //拓展之后一定要有一个写入的操作
	*返回值:文件的大小(字节为单位) 
	********************************************************/
	//读取文件大小
	int ret =lseek(fd,0,SEEK_END);
	printf("file length=%d\n",ret);
	//拓展文件大小(最后一定要有一个写的操作)
	ret =lseek(fd,2000,SEEK_END);
	printf("file length=%d\n",ret);
	write(fd,"a",1);//''不行
	close(fd);
	return 0;
}
  • stat()
    1>终端命令的方式:stat 文件名字
    显示显示的内容比: ls test_lseek.c丰富.
    2>实际运用
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<stdio.h>
#include <unistd.h>
#include<stdlib.h>


int main(int argc,char* argv[])
{
	if(argc<2)
	{
		printf("please cin ./b.c' filename");
	}
	/*******************************************************
	*函数:stat() 
	*头文件:  #include <sys/types.h>  #include <unistd.h>   #include <sys/stat.h> 三个
	*格式: int stat(const char *pathname, struct stat *buf);	//1.传入的是文件地址; 2.struct stat *buf:形参为结构体指针,则需要在外部准备空间(等价于传出参数)3.该函数是一个穿透函数(比如访问软链接文件时(ln -s 绝对地址 名字),其实访问的是源文件)
	*      int lstat(const char *pathname, struct stat *buf);	//1,2同理,但该函数是一个不穿透函数(就是访问的文件自己)
	*      int fstat(int fd, struct stat *buf);			//fd(需要以open()函数打开文件,不需要地址)
	*返回值:On  success,  zero is returned.  On error, -1 is returned, and errno is
       set appropriately.
	********************************************************/
	struct stat buf; 
	//获取当前路径下a.c文件的大小
	int ret=stat(argv[1],&buf);  //argv[]已经是路径了,无需加"";
	if(ret==-1)
	{
		perror("stat file erro");
		exit(1);
	}
	//获取文件大小,可获取量细节可看下图(stat结构体)
	int size_n=(int)buf.st_size;  //off_t转换int
	printf("argv[1]的大小是%d\n",size_n);
	return 0;
}

在这里插入图片描述

  • truncate
    1>文件扩展
	/*******************************************************
	*函数:truncate() 
	*头文件:  #include <sys/types.h>  #include <unistd.h>
	*格式: int truncate(const char *path, off_t length); //文件本身为100,当length为20时,执行完该函数后文件就为20,如果为lengrh为100,执行完后则为200,且无需写操作(区别lseek())
	*       int ftruncate(int fd, off_t length);
	*返回值:0-成功;-1-失败;
	********************************************************/
  • 其他
    1>

在这里插入图片描述
2>unlink

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


int main()
{
	int fd=open("test_unlink.c",O_RDWR|O_CREAT,777);
	if(fd==-1)
	{
		perror("open file error");
		exit(1);
	}
	/*******************************************************
	*函数:unlink() 
	*头文件:#include <unistd.h>
	*格式:int unlink(const char *pathname);
	*作用:创建临时文件
	*返回值:0-成功;-1-失败;
	********************************************************/
	int ret=unlink("./test_unlink.c");//当文件fd存在时,不会删除,只有当文件关闭才会执行该操作.
	if(ret==-1)
	{
		perror("unlink file error");
		exit(1);
	}
	//证明该文件确实存在,我们写入hello,world!到文件里,然后再把它打印到显示屏.
	write(fd,"hello,world!\n",13);
	//重置文件指针
	lseek(fd,0,SEEK_SET);
	//读出内容
	char buf[20];
	int len=read(fd,buf,sizeof(buf));
	//输出到屏幕
	write(1,buf,len);
	close(fd);
	return 0;
}

目录

  • chdir()和getcwd()
    在这里插入图片描述

注意是修改当前进程的目录路径

  • mkdir()和rmdir()
    在这里插入图片描述注意:创建目录时要给定执行权限,不然打不开.
  • opendir()和readdir()和closedir()
    1> 查看man文档:man 3 函数名 //3 -第三章
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<stdio.h>
#include <unistd.h>
#include<stdlib.h>
#include <dirent.h>
//获取文件个数
int get_file_number(char * path,int file_total)
{
	//打开目录
	/*******************************************************
	*函数:opendir() 
	*头文件:#include <sys/types.h>  #include <dirent.h>
	*格式:DIR *opendir(const char *name); //给定目录路径就可,返回一个DIR*
	*作用:打开目录
	*返回值:正确时,函数返回指向目录流的指针。 错误时,将返回NULL,并正确设置了errno。
	********************************************************/
	DIR * dir=NULL;
	dir=opendir(path);  //正确时,函数返回指向目录流的指针。指针指向结构体,包含目录的各种属性,相当于FILE* 一样.
	if(dir==NULL)
	{
		perror("opendir error");
		exit(1);
	}
	//遍历当前打开的目录
	/*******************************************************
	*函数:readdir() 
	*头文件:#include <dirent.h>
	*格式:struct dirent *readdir(DIR *dirp); //返回指向dirent结构的指针,输入目录
	*作用:打开目录
	*返回值:readdir()函数返回一个指向dirent结构的指针,该结构表示dirp指向的目录流中的下一个目录条目。 在到达目录流的末尾时返回NULL
	*	struct dirent 
	*	     {
	*          ino_t          d_ino;        //inode number 
   	*          off_t          d_off;        //not an offset; see NOTES 
    *          unsigned short d_reclen;     //length of this record 
 	*          unsigned char  d_type;       //type of file; not supported by all filesystem types 文件类型6种,见下面的图片
   	*          char           d_name[256];  //filename 
    *        };
	********************************************************/
	struct dirent *ptr=NULL;
	char path_[1024]={0};
	while((ptr=readdir(dir))!=NULL)//当前目录读完返回NULL.
	{
		//分别判断打开的目录还是文件
		//过滤.和..
		if(strcmp(ptr->d_name,".")==0||strcmp(ptr->d_name,"..")==0)
		{
			continue;
		}
		if(ptr->d_type==DT_DIR)
		{
			//连接新的目录地址
			sprintf(path_,"%s/%s",path,ptr->d_name);
			//递归目录
			file_total=get_file_number(path_,file_total);
		}
		if(ptr->d_type==DT_REG)
		{
			file_total++;
		}
	}
		closedir(dir);//要先关闭目录,再返回值.
		return file_total;

}
/*******************************************************
*读取某个目录下文件个数(目录要递归,文件要遍历)
********************************************************/
int main(int argc,char *argv[])
{
	if(argc<2)
	{
		printf("please cin a.out ");
		exit(1);
	}
	int file_total=get_file_number(argv[1],0);
	printf("%s该目录下的文件总数为%d\n",argv[1],file_total);
	return 0;
}

d_type-文件类型
在这里插入图片描述

  • dup()和dup2()
    1>文件描述符的复制
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<stdio.h>
#include <unistd.h>
#include<stdlib.h>
#include <dirent.h>	
int main()
{
	int fd=open("a.c",O_RDWR);
	int fd1=open("b.c",O_RDWR);
	/*******************************************************
	*函数:dup() 
	*头文件:#include <unistd.h>
	*格式:int dup(int oldfd);//返回新的fd,于oldfd都可操作对应的文件(注意文件的指针,打开之后文件指针指向文件头部,如果写入内容旧的内容会被覆盖) (相当于文件描述符取别名,返回别名)
	*	   int dup2(int oldfd, int newfd);//当newfd文件是打开时,先关闭newfd文件,然后 oldfd和newfd都指向原oldfd对应的文件
	*返回值:On success, these system calls return the new descriptor.  On error, -1 is returned, and errno is set appropriately.
	********************************************************/
	int newfd=dup2(fd1,fd);
	char buf[10]="2222";
	lseek(fd1,0,SEEK_END); //文件指针定位到文件末尾防止覆盖
	write(fd,buf,sizeof(buf));//此时fd和fd1都指向b.c进行操作.a.c已经被关闭.
	write(fd1,buf,sizeof(buf));
	close(fd);
	close(fd1);
	return 0;
}
  • fcntl()
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<stdio.h>
#include <unistd.h>
#include<stdlib.h>

int main()
{
	char *p="hao";
	char *q="good";
	int fd=open("a.c",O_WRONLY);//只写权限
	if(fd==-1)
	{
		perror("open file error");
		exit(1);
	}

	if(write(fd,p,strlen(p))==-1)//此时写,文件指针在头部,会进行覆盖.
	{
		perror("write file error");
		exit(1);
	}
	
	/*******************************************************
	*函数:fcntl() 
	*头文件:#include <unistd.h>   #include <fcntl.h>
	*格式: int fcntl(int fd,int cmd,long arg);  //cmd有两种选择:F_GETFL时,获取文件状态,此时第三个参数设置为0;F_SETFL时,第三个参数只有两种选择,O_APPEND和O_NONBLOCX(分别实现文件在打开后改变属性,实现末尾追加写,或则非阻塞模式)
	*返回值:-1-失败  ; >0 文件状态
	********************************************************/
	//使用fcntl()获取文件标记
	int flag=fcntl(fd,F_GETFL,0);
	if(flag==-1)
	{
		perror("fcntl getflag error");
		exit(1);
	}
	flag|=O_APPEND;//更改flag的值,不能写成flag==O_APPEND;
	//使用fcntl()改变当前文件的状态
	if(fcntl(fd,F_SETFL,flag)==-1)
	{
		perror("fcntl settflag error");
		exit(1);
	}
	if(write(fd,q,strlen(q))==-1)//此时写,文件指针在尾部,不会进行覆盖.
	{
		perror("write file error");
		exit(1);
	}
	close(fd);
	return 0;
}
	/*******************************************************
	*总结:将文件指针设置在末尾的方法如下:
	*1.使用open函数:open("...",O_WRONLY|O_APPEND)//O_APPEND 以追加的方式打开,同理O_NONBLOCK: 打开时不阻塞
	*2.使用lseek()函数:lseek(fd,0,SEEK_SET);
	*3.使用fcntl()函数:先获取已经打开文件的文件状态,然后再设置.
	********************************************************/

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值