当前位置: 首页 > news >正文

IO进程线程3

目录

一、文件IO

  1.1 文件IO的概念

  1.2 什么是文件描述符

  1.3 特殊的文件描述符

  1.4 文件IO函数

    1.4.1 open

open代码示例

    1.4.2 umask

    1.4.3 close

    1.4.4 write

write代码示例

    1.4.5 read

read代码示例

    1.4.6 lseek

lseek的代码示例

二、获取文件信息

  2.1 stat

  2.2 获取文件所属用户 getpwuid

  2.3 获取文件所属组名getgrgid

  2.4 获取文件类型和权限

三、目录相关函数

  3.1 opendir

  3.2 closedir

  3.3 readdir

opendir| closedir|readdir代码示例

四、练习

  4.1 使用文件IO读取图片 文件大小、文件偏移量,宽度,高度

  4.2 向一个程序中输入文件名,判断指定目录下是否有这个文件,如果有这个文件,将这个文件的属性信息输出。如果不存在输出不存在即可。


一、文件IO

  1.1 文件IO的概念

        文件IO:指程序和文件系统之间的数据交互

        特点:

        1.不存在缓冲区,访问速度慢

        2.不可以移植,依赖于操作系统

        3.可以访问不同的文件类型(软连接,块设备等)

        4.文件IO属于系统调用

        5.文件IO在操作文件时使用文件描述符

  1.2 什么是文件描述符

        当操作一个文件的时候,则需要创建并打开一个文件,系统就会给文件分配一个编号,这个编号就是文件描述符

        文件描述符本质就是数组的下表,标准IO是对文件IO的二次封装,所以FILE结构体里面存在文件描述符int _fileno;

        1.文件描述符:文件描述符的本质就是数组的下表,默认共有1024个文件描述符,范围[0-1023]

        ulimit -a 查看文件描述符的总个数

        修改文件描述符的个数(修改只对当前终端有效)

        ulimit -n 个数 ---》ulimit -n 2048

        2.文件描述符的申请规则:分配从小到大,未申请的文件描述符

        举例:申请4个文件,则文件描述符 3 4 5 6,关闭4文件描述符,重新申请则文件描述符是最小的编号4

        3.因为文件描述符的个数有限,所以在不适用的情况下,需要关闭

        4.查看中的文件描述符的个数函数

       

功能:查看文件描述符的总个数
格式:
  #include <unistd.h>

  int getdtablesize(void);
返回值:
    返回文件描述符的总个数

  1.3 特殊的文件描述符

        stdin--->0

        stdout--->1

        stderr--->2

  1.4 文件IO函数

        open   close   write   read   lseek

    1.4.1 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);
       函数格式:
        int open(const char *pathname, int flags, ...);
参数:
    pathname:指定打开文件的路径以及文件名
    flags:
          必须包含以下三个之一
          O_RDONLY   只读
          O_WRONLY,   只写
          O_RDWR       读写
         ——————————————————————
         此外,还可以添加以下选项,注意需要使用安位或链接
         O_APPEND    追加
         O_CREAT     创建
         O_TRUNC     清空
         ————————————————————————————————
         eg: 表示标准IO中的w权限
         "w": ----> O_WRONLY | O_CREAT|  O_TRUNC
            #define O_WRONLY    00000001
            #define O_CREAT     00000100
            #define O_TRUNC     00001000
        _________________________________
                                00001101   ---->保留所有权限                     
    mode:可有可无
        mode是由 flags中的O_CREAT 决定的
        如果flags指定O_CREAT,则mode不可以忽略,需要写创建文件权限  eg:0664 0777
        如果flags没有指定O_CREAT,则mode可以忽略
        如果flags指定O_CREAT,并且文件已经创建,则mode不起效果 
        mode指定权限,但是实际的权限是(mode & ~umask)
返回值:
    成功返回新的文件描述符
    失败返回-1,跟新errno
 _______________________________       
eg:    使用文件io函数以w的方式打开
    open("./one.txt",O_WRONLY | O_CREAT|  O_TRUNC,0777)        
    open("./one.txt",O_RDONLY )      

open代码示例

    1.4.2 umask

        1.什么是umask

                umask是文件权掩码

        2.查看文件权限掩码umask

                umask

        3.修改文件权限掩码

                1.shell指令(只对当前终端有效)

                        umask 修改的值 ---->umask 0

                2.使用函数实现修改文件权限掩码(只对当前终端有效)

  #include <sys/stat.h>

       mode_t umask(mode_t cmask);
功能:修改文件权限掩码
参数:cmask  修改权限掩码的值
返回值:
    返回上一个权限掩码值,如果是第一次修改则返回0
eg:    
    umask(0)

    1.4.3 close

格式
    #include <unistd.h>

  int close(int fd);
功能:通过文件描述符关闭文件
参数:
    int fd: open函数打开的文件描述符
返回值:
      成功返回0,失败返回-1,跟新errno  

    1.4.4 write

功能:把数据转换为二进制文件,写入到文件中,在文件中以字符的形式展示
格式:
 #include <unistd.h>

 ssize_t write(int fd, const void *buf, size_t count);
参数:
    int fd: 文件描述符
    void *buf: 写入内容的首地址
    count: 写入的字节大小
返回值:
    成功返回写入的字节数,失败返回-1,跟新errno
write代码示例

    1.4.5 read

功能:根据文件描述符实现文件读取
格式:
 #include <unistd.h>

 ssize_t read(int fd, void *buf, size_t count);
参数:
    fd: 文件描述符
    buf:存储读取的内容
    count: 读取的字节大小
返回值:
    成功返回读取的字符
    读取到文件结尾,则返回0
    如果读取失败返回-1,跟新errno
read代码示例

    1.4.6 lseek

功能:文件指针的偏移(修改光标所在位置)
 格式:
 #include <sys/types.h>
 #include <unistd.h>

 off_t lseek(int fd, off_t offset, int whence);
参数:
    fd: 文件描述符
  offset: 指针的偏移量,
        如果offset>0  ,指针向后偏移
        如果offset<0   指针向前偏移
        offset=0       指针不偏移
    whence:
            SEEK_SET 把光标设置在起始位置
            SEEK_CUR 把光标设置在当前位置
            SEEK_END 把光标设置在结尾位置
    整个光标的位置   offset+whence  
 返回值:
     成功返回起始到当前位置的偏移量
     失败返回-1,跟新errno
 ——————————————————————————————————————————————————————    
 eg:把文件IO的光标偏移到文件的起始位置
     lseek(fd,0,SEEK_SET)      返回值0   
     lseek(fd,10,SEEK_SET)     返回值10  起始位置到当前偏移后的指针的字节大小
 eg:计算文件大小
    lseek(fd,0,SEEK_END)        起始位置到结尾的字节大小(文件大小  )    
lseek的代码示例

二、获取文件信息

  2.1 stat

功能:获取文件信息(文件类型  文件权限  硬链接数, 用户名 文件所属组, 时间)
        不可以获取软链接文件信息,可以使用lstat函数
 格式:
     #include <sys/types.h>
       #include <sys/stat.h>
       #include <unistd.h>

       int stat(const char *pathname, struct stat *statbuf);
参数:
    pathname:查看文件对应的路径以及文件名
    struct stat statbuf: 文件的所有信息
            struct stat {
          dev_t     st_dev;         /* ID of device containing file */
          ino_t     st_ino;         /* Inode number */   inode号
          mode_t    st_mode;        /* File type and mode */  文件类型和权限
          nlink_t   st_nlink;       /* Number of hard links */  硬链接数
          uid_t     st_uid;         /* User ID of owner */ uid用户id
          gid_t     st_gid;         /* Group ID of owner */   gid组id
          dev_t     st_rdev;        /* Device ID (if special file) */
          off_t     st_size;        /* Total size, in bytes */   文件大小
          blksize_t st_blksize;     /* Block size for filesystem I/O */
          blkcnt_t  st_blocks;      /* Number of 512B blocks allocated */

          /* Since Linux 2.6, the kernel supports nanosecond
             precision for the following timestamp fields.
             For the details before Linux 2.6, see NOTES. */

          struct timespec st_atim;  /* Time of last access */    最后一次访问的时间
          struct timespec st_mtim;  /* Time of last modification */   最后一次修改的时间
          struct timespec st_ctim;  /* Time of last status change */  最后一次状态修改的之间

      #define st_atime st_atim.tv_sec   最后一次访问的时间(秒)
      #define st_mtime st_mtim.tv_sec   最后一次修改的时间(秒)
      #define st_ctime st_ctim.tv_sec   最后一次状态修改的时间(秒)
      };

返回值:
       成功返回0,失败返回-1  跟新errno 

  2.2 获取文件所属用户 getpwuid

功能:根据用户id获取用户对应的信息
格式:
  #include <sys/types.h>
  #include <pwd.h>

 

  struct passwd *getpwuid(uid_t uid);
参数:
    uid   用户id
返回值:
      struct passwd {
               char   *pw_name;       /* username */   用户名
               char   *pw_passwd;     /* user password */
               uid_t   pw_uid;        /* user ID */
               gid_t   pw_gid;        /* group ID */
               char   *pw_gecos;      /* user information */
               char   *pw_dir;        /* home directory */
               char   *pw_shell;      /* shell program */
           };

     成功返回strutc passwd类型的指针,存储用户的相关信息
     失败返回NULL  跟新errno 

  2.3 获取文件所属组名getgrgid

 功能:根据组id,获取组对应的信息
格式:
 #include <sys/types.h>
 #include <grp.h>

 struct group *getgrgid(gid_t gid);
参数:
    gid:   组id
返回值 
    成功返回指向组对应信息的结构体指针
    失败返回NULL,跟新errno      
      struct group {
               char   *gr_name;        /* group name */   组名
               char   *gr_passwd;      /* group password */
               gid_t   gr_gid;         /* group ID */
               char  **gr_mem;         /* NULL-terminated array of pointers
                                          to names of group members */
           };
 

  2.4 获取文件类型和权限

文件类型是由st_mode的高4位决定

权限是由st_mode的第9位决定的

man 7 inode

———————————————————————文件类型—————————————————————————
 方式1:
 switch(st.st_mode& S_IFMT)
 {
 case S_IFSOCK:printf("socket");break;
 case S_IFLNK:printf("symbolic");break;
 case S_IFREG:printf("regular");break;
 case S_IFBLK:printf("block");break;
 case S_IFDIR:printf("directory");break;
 case S_IFCHR:printf("character");break;
 case S_IFIFO:printf("FIFO");break;
 }
方式2:
 if( S_ISREG(st.st_mode))
     printf("regular");
 else if( S_ISDIR(st.st_mode))
     printf("directory?");
 else if( S_ISCHR(st.st_mode))
     printf("character");
 else if( S_ISBLK(st.st_mode))
     printf("block");
 else if( S_ISFIFO(st.st_mode))
     printf("FIFO");
 else if( S_ISLNK(st.st_mode))
     printf("symbolic");
 else if( S_ISSOCK(st.st_mode))               
     printf("socket");
   
————————————————————————文件权限—————————————————————————
/获取文件权限
 printf("mode=%#o\n",st.st_mode&0777);

三、目录相关函数

  3.1 opendir

功能:打开指定路径下目录
格式:
  #include <sys/types.h>
 #include <dirent.h>

 DIR *opendir(const char *name);
参数:
    name: 打开的目录以及路径
返回值:
    成功返回目录的流指针,失败返回NULL,跟新errno    

  3.2 closedir

功能:关闭目录流指针
格式
      #include <sys/types.h>

   #include <dirent.h>

   int closedir(DIR *dirp);
参数:
    dirp: 目录流指针 就只opendir返回的指针
 返回值:
     成功返回0 失败返回-1 跟新errno   

  3.3 readdir

 功能:读取目录对应的信息
 格式:
     #include <dirent.h>

   struct dirent *readdir(DIR *dirp);
参数:
      dirp: 目录流指针 就只opendir返回的指针
返回值:
            struct dirent {
               ino_t          d_ino;       /* Inode number */   inode号
               off_t          d_off;       /* Not an offset; see below */
               unsigned short d_reclen;    /* Length of this record */  结构体的大小会睡着d_name的实际长度改变而改变
               unsigned char  d_type;      /* Type of file; not supported   类型
                                              by all filesystem types */
               char           d_name[256]; /* Null-terminated filename */   名字
           };
     如果成功,则返回一个struct dirent类型的结构体,结构体中存储目录的相关信息
     如果遇到文件结尾,返回NULL,不更新errno
     如果读取失败,则返回NULL,跟新errno

opendir| closedir|readdir代码示例

四、练习

  4.1 使用文件IO读取图片 文件大小、文件偏移量,宽度,高度

        1.bmp文件头(bmp file header):提供文件的格式、大小等信息 (14字节)

          2 位图信息头(bitmap information):提供图像数据的尺寸、位平面数、压缩方式、颜色索引等信息(40字节)

        3.位图数据(bitmap data):就是图像数据啦

#include "head.h"
int main(int argc, const char *argv[])
{
	int fd=open("./xiaoxin.bmp",O_RDONLY);
	lseek(fd,2,SEEK_SET);
	int size;
	read(fd,&size,4);
	printf("大小:%dB\n",size);
	
	lseek(fd,10,SEEK_SET);
	int offset;
	read(fd,&offset,4);
	printf("偏移量:%d\n",offset);

	lseek(fd,18,SEEK_SET);
	int width;
	read(fd,&width,4);
	printf("宽度:%d\n",width);

	lseek(fd,22,SEEK_SET);
	int high;
	read(fd,&high,4);
	printf("高度:%d\n",high);

	close(fd);
	return 0;
}

  4.2 向一个程序中输入文件名,判断指定目录下是否有这个文件,如果有这个文件,将这个文件的属性信息输出。如果不存在输出不存在即可。

                ./a.out 目录名 查询的文件名

                        argv[1] argv[2]

#include "head.h"
int main(int argc, const char *argv[])
{
	// 检查文件是否存在
	DIR *dp=opendir(argv[1]);
	if(dp==NULL)
	{
		printf("目录不存在\n");
		return 0;
	}
	struct dirent *f=NULL;
	while( f=readdir(dp) )
	{
		if(strcmp(f->d_name,argv[2])==0)
			break;
	}
	if(f==NULL)
	{
		printf("文件不存在");
		return 0;
	}
	closedir(dp);
	
// 打印文件相关信息
	// 获取文件相对路径
	char file[128];
	sprintf(file,"%s/%s",argv[1],argv[2]);

	struct stat st;
	if(stat(file,&st)==-1)
		PRINTF_ERROR("stat error");
	
	// 获取文件权限
	// 获取文件类型
	mode_t mode=st.st_mode;
	switch(mode&0170000)
	{
		case 0010000:
			printf("p");
			 break;
		case 002000:
			printf("c");
			 break;
		case 0040000:
			printf("d");
			 break;
		case 0060000:
			printf("b");
			 break;
		case 0100000:
			printf("-");
			 break;
		case 0120000:
			printf("l");
			 break;
		case 0140000:
			printf("s");
			 break;
		default:
			 printf("error\n");
			 break;
	}
	int chown=mode&0777;
	printf("%#o ",chown);

	// 获取硬链接数
	int num=st.st_nlink;
	printf("%d ",num);

	// 获取用户id
	int id=st.st_uid;
	// 获取用户名
	struct passwd *p=getpwuid(id);
	printf("%s ",p->pw_name);

	// 获取组id
	gid_t gid=st.st_gid;
	// 获取组名
	struct group *gr=getgrgid(gid);
	printf("%s ",gr->gr_name);

	// 获取文件大小
	off_t size=st.st_size;
	printf("%ld ",size);

	// 获取文件id
	ino_t fid=st.st_ino;
	// 获取最后一次访问的时间转换为年月日时分秒
	struct tm *t=localtime(&st.st_atim.tv_sec);
	printf("%d-%d-%d %02d:%02d:%02d ",t->tm_year+1900,t->tm_mon+1,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec);
	
	// 输出文件名
	printf("%s\n",argv[2]);

	
	return 0;
}

相关文章:

  • 【AD】5-3 PCB板框的内缩与外扩
  • OpenBMC:BmcWeb app获取socket
  • 嵌入式 ARM Linux 系统构成(1):Bootloader层
  • oracle通过dmp导入数据
  • PHP之运算符
  • python-串口助手(OV7670图传)
  • 文献分享: ConstBERT固定数目向量编码文档
  • java 查找连个 集合的交集部分数据
  • 生命周期总结(uni-app、vue2、vue3生命周期讲解)
  • Linux总结
  • 进程间通信
  • 【单片机】嵌入式系统设计流程
  • 【仿muduo库one thread one loop式并发服务器实现】
  • 美股回测:历史高频分钟数据的分享下载与策略解析20250305
  • 配置hosts
  • 【软考-架构】9.2、摘要-签名-PKI-访问控制-DOS-欺骗技术
  • SQL注入的原理及详细运用
  • Golang依赖注入实战:从容器管理到应用实践
  • 240 Vocabulary Words Kids Need to Know
  • 计算机组成原理:计算机系统层次结构
  • 牛市早报|持续推进城市更新行动意见印发,证监会强化上市公司募资监管
  • 秦洪看盘|缩量回踩,积蓄叩关能量
  • 宜昌谱写新叙事:长江大保护与高质量发展如何相互成就
  • 互降关税后,从中国至美国的集装箱运输预订量飙升近300%
  • 沧州低空经济起飞:飞行汽车开启千亿赛道,通用机场布局文旅体验
  • 北洋“修约外交”的台前幕后——民国条约研究会档案探研