Linux系统编程—文件IO

一.文件IO 与 标准IO 的对比:

标准IO标准IO
缓冲区全缓存、行缓存、无缓存没有缓存区
操作对象流(FILE *)文件描述符(int fd)
标准输入输入流(stdin)0
标准输出输出流(stdout)1
标准错误错误流(stderr)2
遵从的标准ANSIC 标准POSIX 标准
打开fopenopen
关闭fcloseclose
fgetc/fread/fgetsread
fputc/fputs/fwritewrite
定位fseek, ftelllseek

二.文件IO 函数:

  1. 打开文件:open
    函数原型: int open(const char *pathname, int flags);
         int open(const char *pathname, int flags, mode_t mode);

头文件:#include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>

参数: 参数一: 文件名 (可以包含路径)
   参数二: 打开文件的方式(只读、只写、读写、创建、…)
      O_RDONLY 只读
      O_RDWR 读写
      O_WRONLY 只写
      O_CREAT 创建
      O_TRUNC 清空文件
      O_EXCL 如果创建失败,报错误信息
      O_APPEND 打开文件时,定位到文件尾。
   参数三: 只有在创建文件时,才使用参数三。参数三的功能:创建文件时,文件的权限。

对应的功能与参数:

标准IO文件IO
“r”O_RDONLY
“w”O_WRONLY
“a”O_WRONLY

//示例:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc,char *argv[])
{
	int fd = open(argv[1],O_RDONLY);
	if(fd != -1)
		printf("open success\n");
	else 
		printf("fail to open\n");
	return 0;
}
  1. 关闭文件 close
    函数原型: int close(int fd);
    头文件: #include <unistd.h>
    示例:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main()
{
	int fd = open("a.c",O_WRONLY|O_CREAT|O_TRUNC);
	if(fd == -1)
		return -1;
	printf("%d\n",fd);
	close(fd);
}
  1. 读 read
    函数原型: ssize_t read(int fd,void *buf,size_t count);
             ------------->
    参数:参数二: 从fd中读到的数据,存放在此位置。
       参数三: 申请读取数据的大小。
       返回值: 实际读到的数据的个数 (有可能小于 参数 count)
    头文件: #include <unistd.h>

/示例:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
	char buf[100] = {0};
	int fd = open("cl.c",O_RDONLY);
	if(fd == -1)
	{
		printf("fail to open\n");
		return -1;
	}
	ssize_t s = read(fd,buf,20);
	printf("read buf: %s\n",buf);
	close(fd);
	return 0;
}

//练习: 实现shell命令 cat 的功能。

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
//#include <strings.h>
#include <string.h>
int main(int argc,char *argv[])
{
	if(argc < 2)
	{
		printf("%s  <filename>\n",argv[0]);
		return -1;
	}
	char buf[100] = {0};
	int fd = open(argv[1],O_RDONLY);

	ssize_t n = read(fd,buf,100);
	while(n != 0)
	{
		printf("%s",buf);
//		bzero(buf,100);
		memset(buf,0,100);
		n = read(fd,buf,100);
	}
	close(fd);
	return 0;
}
  1. 清零函数 bzero memset
    4.1 bzero
    函数原型: void bzero(void *s,size_t n);
    函数参数: 参数一: 没有指定类型。 可以是任意类型的一块空间,s指向其空间首地址。
         参数二: s 空间多大。
    函数功能: 将 s 这片 连续空间的n个字节 清零。
    头文件: #include <strings.h>
    4.2 memset
    函数原型: void *memset(void *s,int c,size_t n);
    函数功能: 将 s这个连续n个字节 的空间,统一填充 c。
    参数: 参数一: s 指向一片连续空间
    参数二: 空间填充的数值。
    参数三: s指向的空间 的大小。
    //示例: 见上例。

  2. 写 write
    函数原型: ssize_t write(int fd,const void *buf,size_t count);
    函数功能: 将 buf 中的数据,写入到 fd 中。

//示例:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main(int argc,char *argv[])
{
	if(argc < 2)
	{
		printf("%s <filename>\n",argv[0]);
		return -1;
	}

	char buf[100] = "Hello world!";
	int fd = open(argv[1],O_WRONLY|O_TRUNC);   //如果权限中没有 O_TRUNC,那么源文件不清空。 
	if(fd == -1)              				   //加上这个权限后,才清空源文件,然后再写。 
		return -1;
	write(fd,buf,strlen(buf));
	
	close(fd);
	return 0;
}

//练习: 使用 read write,实现拷贝文件的功能。

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

int main(int argc,char *argv[])
{
	if(argc < 3)
	{
		printf("%s <src> <dest> \n",argv[0]);
		return -1;
	}

	char buf[100] = {0};
	int fds = open(argv[1],O_RDONLY);
	int fdd = open(argv[2],O_RDWR|O_TRUNC|O_CREAT,0777);

	ssize_t n = read(fds,buf,100);
	while(n != 0)
	{
		write(fdd,buf,n);
		bzero(buf,100);
		n = read(fds,buf,100);
	}
	close(fds);
	close(fdd);
	return 0;
}
  1. 定位 lseek
    函数原型: off_t lseek(int fd, off_t offset, int whence);
    头文件: #include <sys/types.h>
         #include <unistd.h>
    参数: 参数一: 文件描述符。
       参数二: 偏移量是多少。
       参数三: 偏移位置:
          SEEK_SET 文件开头。
          SEEK_CUR 当前位置。
          SEEK_END 文件末尾。

返回值: 偏移量的大小(从文件开头算起)
//示例:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main(int argc,char *argv[])
{
	if(argc < 2)
	{
		printf("%s <filename>\n",argv[0]);
		return -1;
	}

	char string[] = "Struggle for a better future";
	char buf[100] = {0};
	int fd = open(argv[1],O_RDWR);
	if(fd == -1)
		return -1;

	ssize_t n = write(fd,string,strlen(string)+1);   //将string中的内容写到文件 fd 中。 
	off_t pos = lseek(fd,0,SEEK_SET);   //文件写完之后,定位位置是在文件末尾,所以读文件之前,要把定位重新放到文件开头。 
	printf("pos : %ld\n",pos);
	read(fd,buf,n);	  //从文件的起始位置开始读取。lseek(fd,0,SEEK_SET) 将读取位置重新置到文件开头。 
	close(fd);
	
	puts(buf);
	return 0;
}

三.目录文件

  1. 打开目录 opendir
    函数原型: DIR *opendir(const char *name);
    头文件: #include <sys/types.h>
        #include <dirent.h>
    参数: 目录名称。
    返回值: 成功: 指向目录的指针。
        失败: NULL
  2. 关闭目录 closedir
    函数原型: int closedir(DIR *pd);
    头文件: #include <sys/types.h>
        #include <dirent.h>
    返回值: 成功: 返回 0 .
        失败: 返回 -1 .

//示例:

#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
int main()
{
	DIR *pdir = opendir("/home/linux/HELLO");
	if(!pdir)
	{
		printf("Fail to open\n");
		return -1;
	}
	else
	{
		printf("OK\n");
		closedir(pdir);
	}
	return 0;
}
  1. 读文件: readdir
    函数原型: struct dirent *readdir(DIR *dirp);
    头文件: #include <dirent.h>
    参数: opendir 的返回值。
    返回值:失败: NULL
        成功: 一个结构体指针: struct dirent *
    结构体:
struct dirent {
       ino_t          d_ino;       /* inode number */  
       off_t          d_off;       /* offset to the next dirent */
       unsigned short d_reclen;    /* length of this record */
       unsigned char  d_type;      /* type of file; not supported
                                      by all file system types */
       char           d_name[256]; /* filename */
   };

//示例:

#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
int main()
{
	DIR *pdir = opendir("/home/linux");
	if(!pdir)
	{
		printf("Fail to open\n");
		return -1;
	}
	struct dirent *p = readdir(pdir);	
	printf("ino :%ld --- type : %d  --- name : %s \n",p->d_ino,p->d_type,p->d_name);
	closedir(pdir);
	
	return 0;
}

//练习: 查看 /home 下的所有文件信息: inode name …

#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
int main()
{
	DIR *pdir = opendir("/home");
	if(!pdir)
	{
		printf("Fail to open\n");
		return -1;
	}
	struct dirent *p = readdir(pdir);	
	while(p)
	{
//		if(p->d_name[0]  != '.')
			printf("ino :%-8ld --- type : %u  --- name : %-8s \n",p->d_ino,p->d_type,p->d_name);
		p = readdir(pdir);
	}
	closedir(pdir);
	
	return 0;
}  
  1. 文件属性 stat fstat lstat
    函数原型: int stat(const char *path, struct stat *buf);
          int fstat(int fd, struct stat *buf);
          int lstat(const char *path, struct stat *buf);
    头文件: #include <sys/types.h>
        #include <sys/stat.h>
       #include <unistd.h>

参数: 参数一: 目录名称。
   参数二: 是结构体指针。

struct stat {
       mode_t    st_mode;    /* protection */
	   uid_t     st_uid;     /* user ID of owner */
       gid_t     st_gid;     /* group ID of owner */
       off_t     st_size;    /* total size, in bytes */
       time_t    st_atime;   /* time of last access */
       time_t    st_ctime;   /* time of last status change */
	   ...
   };

  关于结构体中的 st_mode:在POSIX 标准中,为用户提供以下带参宏,来检测文件的属性。

The following POSIX macros are defined to check the file type using the st_mode field:
       S_ISREG(m)  is it a regular file?    //是否为普通文件? 是,返回真;不是,返回假。 
       S_ISDIR(m)  directory? 			//是否为目录文件?
       S_ISCHR(m)  character device?  //字符设备?
       S_ISBLK(m)  block device?   //块设备?
       S_ISFIFO(m) FIFO (named pipe)?  //管道文件?

//示例:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int main()
{
	struct stat a;
	stat("/home/linux",&a);

	printf("ctime: %ld,size : %ld, uid : %u  \n",a.st_ctime,a.st_size,a.st_uid);
	
	return 0;
}	

//带参宏-示例:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int main()
{
	struct stat a;
	stat("/home/linux/rand",&a);

	if(S_ISDIR(a.st_mode))
		printf("It's dir \n");
	else if(S_ISREG(a.st_mode))
		printf("It's file\n");
	else
		printf("Not dir \n");

	return 0;
}

//练习: 遍历用户工作目录中的所有文件。标明文件类型:

#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
 
int main()
{
	DIR * dirp = opendir(".");
	if(!dirp)
		return -1;

	struct stat buf;
	struct dirent *readp = readdir(dirp);
	if(!readp)
	{
		perror("readdir");		
		return -1;
	}
	while(readp)
	{
		stat(readp->d_name,&buf);
	
		if(S_ISDIR(buf.st_mode) && readp->d_name[0] != '.')
			printf("%8s  <---------- dir \n",readp->d_name);

		if(S_ISREG(buf.st_mode) && readp->d_name[0] != '.')
			printf("%8s  : file \n",readp->d_name);

		readp = readdir(dirp);
	}
	closedir(dirp);
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值