文件IO函数

目录

 文件描述符

1. 概念

2. 特殊的文件描述符

3. 文件描述符的总量

 文件IO的函数

 1.open

2.umask

i. umask是什么

ii. 获取umask的值

iii. 修改umask的值

3.close

4.write

5.read

 6.lseek

目录相关的函数

1.opendir

2.closedir

3.readdir

获取文件属性

1.stat

2.提取文件的权限

3.提取文件的类型

 方法一

方法二

4.提取文件所属用户名

 4.提取文件所属组用户名

  1. 文件IO是不带缓冲区的。
  2. 文件IO函数是由操作系统提供的,与操作系统绑定,又称之为系统调用。
  3. 标准IO是通过流指针维护一个文件,文件IO是通过文件描述符来维护一个文件。

 文件描述符

1. 概念

  1. 尝试打开一个文件的时候,系统会自动给这个文件分配一个编号,用这个编号来描述这个文件。这个编号就是文件描述符。
  2. 文件描述符的本质:数组下标。在main函数启动前,操作系统会帮助我们在用户空间创建一个数组(文件描述符表),且容量默认为1024. 范围是[0, 1023]
  3. 文件描述符申请原则:从小到大依次遍历,直到遇到没有被使用的文件描述符

 

2. 特殊的文件描述符

特殊的流指针

特殊的文件描述符

FILE* stdin

stdin->_fileno

0

FILE* stdout

stdout->_fileno

1

FILE* stderr

stderr->_fileno

2

 结果为0 1 2

3. 文件描述符的总量

默认是1024个

  1. 循环打开不关闭,直到超出打开上限,得到文件描述符总量。
  2. getdtablesize()函数:获取操作系统的文件描述符总量。 printf("%d\n", getdtablesize());

 文件IO的函数

 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);
参数:
    char *pathname:指定要打开的文件的路径和名字;
    int flags:打开方式
        O_RDONLY     只读, 
        O_WRONLY     只写,
        O_RDWR       读写
    ----以上三种必须包含一种----------
        O_APPEND     追加方式打开,
        O_TRUNC      清空,若文件存在,且是一个普通文件,且以写的方式打开
        O_CREAT      若文件不存在,则创建一个普通文件。
    若有多个选项合成一个打开方式,则用按位或连接:
        "w":O_WRONLY | O_CREAT | O_TRUNC
        
    mode_t mode:用来指定文件创建的时候的权限,例如:0664
                若flags中包含了O_CREAT或者O_TMPFILE的时候,就必须写mode参数;
                若flags没有O_CREAT或者O_TMPFILE的时候,会忽略mode参数;
返回值:
    成功,返回文件描述符,
    失败,返回-1,更新errno;

 代码展示

 标准IO中的 r r+ w w+ a a+,用文件IO中的flags进行组合。

          ┌─────────────┬───────────────────────────────┐
          │fopen() mode │ open() flags                  │
          ├─────────────┼───────────────────────────────┤
          │     r       │ O_RDONLY                      │
          ├─────────────┼───────────────────────────────┤
          │     w       │ O_WRONLY | O_CREAT | O_TRUNC  │
          ├─────────────┼───────────────────────────────┤
          │     a       │ O_WRONLY | O_CREAT | O_APPEND │
          ├─────────────┼───────────────────────────────┤
          │     r+      │ O_RDWR                        │
          ├─────────────┼───────────────────────────────┤
          │     w+      │ O_RDWR | O_CREAT | O_TRUNC    │
          ├─────────────┼───────────────────────────────┤
          │     a+      │ O_RDWR | O_CREAT | O_APPEND   │
          └─────────────┴───────────────────────────────┘

2.umask

the mode of the created file is (mode & ~umask).

文件创建时候的真实权限是 mode & ~umask

mode : 0777 ----> 111 111 111
umask?            111 111 101==> ~umask ---> umask = 000 000 010 = 0002
结果: 0775 ----> 111 111 101

i. umask是什么

文件权限掩码,目的就是影响文件创建时候的权限。可以通过设置umask的值保证某些用户肯定没有某些权限。

ii. 获取umask的值

终端输入:umask

iii. 修改umask的值

  1. 终端输入: umask 0 只在设置终端有效
  2. umask()函数
       #include <sys/types.h>
       #include <sys/stat.h>

       mode_t umask(mode_t mask);
       
umask(0);

3.close

功能:关闭文件; 释放文件描述符;
原型:
       #include <unistd.h>

       int close(int fd);
参数:
    int fd:指定要关闭的文件描述符;
返回值:
    成功,返回0;
    失败,返回-1,更新errno;

4.write

功能:将数据写入到文件中; 
原型:
       #include <unistd.h>

       ssize_t write(int fd, const void *buf, size_t count);
参数:
    int fd:指定要将数据写入到哪个文件中,填对应的文件描述符;
    void *buf:指定要输出的数据的首地址,可以是任意类型数据;
    size_t count:指定要输出的数据字节数;
返回值:
    成功,返回成功输出的字节数;
    失败,返回-1,更新errno;

注意,write函数指定写多少个字节,就会从内存中拿多少个字节,写入到文件中,即使越界

5.read

功能:从文件中读取数据;
原型:
       #include <unistd.h>

       ssize_t read(int fd, void *buf, size_t count);
参数:
    int fd:指定要从哪个文件中读取数据,填对应的文件描述符;
    void *buf:指定要将读取到的数据存储到那块空间中,可以是任意类型数据;
    size_t count:指定要读取的数据字节数;
返回值:
    >0, 成功,返回成功读取的字节数;
    =0, 文件读取完毕;
    =-1, 失败,返回-1,更新errno;

 代码展示

 6.lseek

功能:修改文件偏移量;
原型:
       #include <sys/types.h>
       #include <unistd.h>

       off_t lseek(int fd, off_t offset, int whence);
参数:
    int fd:文件描述符;
    off_t offset: 距离whence参数指定的偏移量。往前偏移填负数, 往后偏移填正数
    int whence:
       SEEK_SET,  文件开头位置
       SEEK_CUR,  文件当前位置
       SEEK_END   文件结尾位置
返回值:
    成功,修改偏移量后,文件当前位置距离文件开头的偏移量;
    失败,返回-1,更新errno;    
    
    //计算文件大小
    off_t size = lseek(fd_r, 0, SEEK_END);
    printf("size=%ld\n", size);

若偏移量在文件开头,能否继续往前偏移 ---》 不行

若偏移量在文件结尾,能否继续往后偏移 ---》可以

目录相关的函数

1.opendir

功能:打开一个目录文件;
原型:
       #include <sys/types.h>
       #include <dirent.h>

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

2.closedir

功能:关闭目录;
原型:
       #include <sys/types.h>

       #include <dirent.h>

       int closedir(DIR *dirp);

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

3.readdir

功能:读取目录;
原型:
       #include <dirent.h>

       struct dirent *readdir(DIR *dirp);
参数:
返回值:
    成功,返回结构体指针:
    失败,返回NULL; 更新errno;
    目录读取完毕,返回NULL,不更新errno;
         struct dirent {
               ino_t          d_ino;       /* Inode number */
               off_t          d_off;       /* Not an offset; see below */
               unsigned short d_reclen;    /* Length of this record */
               unsigned char  d_type;      /* Type of file; not supported
                                              by all filesystem types */
               char           d_name[256]; /* Null-terminated filename */
           };

获取文件属性

-           rw-rw-r--  1              ubuntu       ubuntu         372   七月 31 11:29      01_fileno.c
文件的类型    文件权限  文件的硬链接数  文件所属用户   文件所属组用户  大小

文件的类型 : bsp-lcd
文件权限: rw-   rw-   r--    文件所属用户权限 组用户权限  其他用户权限

1.stat

功能:获取文件的属性;
原型:
       #include <sys/types.h>
       #include <sys/stat.h>
       #include <unistd.h>

       int stat(const char *pathname, struct stat *statbuf);
参数:
    char *pathname:指定要获取属性的文件路径以及名字;
    struct stat *statbuf:存储获取到的属性;
返回值:
    成功,返回0;
    失败,返回-1,更新errno;
    
vi -t stat 或者 man手册往下翻
          struct stat {

               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
               gid_t     st_gid;         /* Group ID of owner */    组用户的gid

               off_t     st_size;        /* Total size, in bytes */     文件大小


               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      /* Backward compatibility */
           #define st_mtime st_mtim.tv_sec
           #define st_ctime st_ctim.tv_sec
           };

2.提取文件的权限

mode_t    st_mode   本质上是一个unsigned int类型,里面存储了文件的类型和权限。
st_mode中其中低9bits存储了文件的权限:[0bit - 8bit]
mode: 0100664 ---> rw-rw-r--
        664----> 110 110 100 ---> 0664
                 100 000 000 ---> 0400
                 ------------
                 100 000 000 ===> 0400结果不等于0,需要打印'r'。否则打印'-'
                 
        664----> 110 110 100 ---> 0664
                 010 000 000 ---> 0200
                 ------------
                 010 000 000 ===> 0200结果不等于0,需要打印'w'。否则打印'-'
                 
        664----> 110 110 100 ---> 0664
                 001 000 000 ---> 0100
                 ------------
                 000 000 000 ===> 0000结果等于0,需要打印'-'。否则打印'x'
void get_filePermission(mode_t m)   //mode_t m = buf.st_mode
{
    char buf[] = "rwx";

    for(int i=0; i<9; i++)
    {
        if( (m & (0400>>i)) == 0)
        {
            putchar('-');
            continue;
        }

        //能运行到当前位置,则代表对应位置有权限
        //需要判断是r w x中的哪一个
        /*
        switch(i%3)
        {
        case 0:
            putchar('r');
            break;
        case 1:
            putchar('w');                                   
            break;
        case 2:
            putchar('x');
            break;
        }
        */

        printf("%c", buf[i%3]);

    }
    return;
}

3.提取文件的类型

mode_t st_mode 本质上是一个unsigned int类型,里面存储了文件的类型和权限。

 方法一

man 2 stat --> st_mode --->see inode(7)
man 7 inode -->

           S_ISREG(m)  is it a regular file?                         -

           S_ISDIR(m)  directory?                                    d

           S_ISCHR(m)  character device?                             c

           S_ISBLK(m)  block device?                                 b

           S_ISFIFO(m) FIFO (named pipe)?                            p

           S_ISLNK(m)  symbolic link?  (Not in POSIX.1-1996.)        l

           S_ISSOCK(m) socket?  (Not in POSIX.1-1996.)               s
若是该类型文件,则返回真,否则返回假

void get_fileType(mode_t m) 
{
    if(S_ISREG(m))
        putchar('-');

    else if(S_ISDIR(m))
        putchar('d');

    else if(S_ISCHR(m))
        putchar('c');       

    return ;

}

方法二

mode       0040775
S_IFMT     0170000   bit mask for the file type bit field

mode       0040775 ---> 000 100 000 111 111 101
S_IFMT     0170000 ---> 001 111 000 000 000 000  &
                    ------------------------------
                        000 100 000 000 000 000 ---> 040000
与下列宏进行比较,与哪个相同,就是对应类型文件
           S_IFSOCK   0140000   socket
           S_IFLNK    0120000   symbolic link
           S_IFREG    0100000   regular file
           S_IFBLK    0060000   block device
           S_IFDIR    0040000   directory
           S_IFCHR    0020000   character device
           S_IFIFO    0010000   FIFO

mode:      0100664 ---> 001 000 000 110 110 100
S_IFMT     0170000 ---> 001 111 000 000 000 000  &
                    ------------------------------
                        001 000 000 000 000 000 ---> 0100000
void get_fileType(mode_t m)     //mode_t m = buf.st_mode
{   
    switch(m & S_IFMT)
    {
    case S_IFSOCK: putchar('s');    break;
    case S_IFLNK: putchar('l');     break;
    case S_IFREG: putchar('-');     break;
    case S_IFDIR: putchar('d');     break;
    }

    return;                                              
}

4.提取文件所属用户名

uid_t st_uid; /* User ID of owner */ 用户的uid

功能:通过uid号获取用户的信息;
原型:
       #include <sys/types.h>
       #include <pwd.h>


       struct passwd *getpwuid(uid_t uid);
参数:
    uid_t uid:指定uid号;
返回值:
    成功,返回结构体指针;
    失败,返回NULL;更新errno;
           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 */
           };

   struct passwd* pwd = getpwuid(buf.st_uid);
   if(NULL == pwd)
   {
       ERR_MSG("getpwuid");
       return -1;
   }
   printf("%s\n", pwd->pw_name);

 4.提取文件所属组用户名

gid_t st_gid; /* Group ID of owner */ 组用户的gid

功能:通过gid号获取组用户的信息;
原型:
       #include <sys/types.h>
       #include <grp.h>


       struct group *getgrgid(gid_t gid);
参数:
    gid_t gid:指定gid号;
返回值:
    成功,返回结构体指针;
    失败,返回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 */
           };

    struct group* grp = getgrgid(buf.st_gid);
    if(NULL == grp)
    {                                             
        ERR_MSG("getgrgid");
        return -1;
    }
    printf("%s\n", grp->gr_name);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ck钉钉钉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值