基于文件描述符的文件操作(四):获取文件信息

By AverageJoeWang
 标签:

一.概述

linux的哲学是一切皆文件,所在获取文件的的信息尤其重要,知道文件的属性就能够知晓linux相关的运行秘密。本篇笔记主要针对Linux/Unix系统提供的stat和fstat函数进行说明.

二.获取文件信息

2.1.fstat与stat原型

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *file_name, struct stat *buf);      //文件名  stat结构体指针
int fstat(int fd, struct stat *buf);              //文件描述词   stat结构体指针
  • 说明

可以通过fstat和stat函数获取文件信息,调用完毕后,文件信息被填充到结构体struct stat变量中

2.2.stat结构体

  • stat结构体的原型为
    struct stat {
           dev_t         st_dev;      /*如果是设备,返回设备表述符,否则为0*/
           ino_t         st_ino;      /* i节点号 */
           mode_t        st_mode;     /* 文件类型 */  无符号短整型
           nlink_t       st_nlink;    /* 链接数 */
           uid_t         st_uid;      /* 属主ID */
           gid_t         st_gid;      /* 组ID */
           dev_t         st_rdev;     /* 设备类型*/
           off_t         st_size;     /* 文件大小,字节表示 */
           blksize_t     st_blksize;  /* 块大小*/
           blkcnt_t      st_blocks;   /* 块数 */
           time_t        st_atime;    /* 最后访问时间*/
           time_t        st_mtime;    /* 最后修改时间*/
           time_t        st_ctime;    /* 最后权限修改时间 */
    };
  • 说明

结构体的成员st_mode,有一组宏可以进行文件类型的判断

描述
S_ISLNK(mode) 判断是否是符号链接
S_ISREG(mode) 判断是否是普通文件
S_ISDIR(mode) 判断是否是目录
S_ISCHR(mode) 判断是否是字符型设备
S_ISBLK(mode) 判断是否是块设备
S_ISFIFO(mode) 判断是否是命名管道
S_ISSOCK(mode) 判断是否是套接字

在调用fstat与stat时候将文件的属性存储在stat结构体中,然后在需要的时候直接访问结构体的相关数据成员

2.3.例子

#include <iostream>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <time.h>
using std::cout;
using std::endl;


int main(int argc, char* argv[])
{
    int fd = open(argv[1], O_RDONLY);//fd存储的是文件描述符
    if(-1 == fd)
    {
        perror("open error");
        return -1;
    }

    struct stat buf;//创建一个文件的信息的结构体变量
    int ret = fstat(fd, &buf);
    if(-1 == ret)
    {
        perror("fstat error");
        close(fd);
        return -1;
    }
//获取文件类型,st_mode
    if(S_ISREG(buf.st_mode))
        cout << "It is a regular file!" << endl;
    else if(S_ISDIR(buf.st_mode))
        cout << "It is a dirent!" << endl;
    else if(S_ISLNK(buf.st_mode))
        cout << "It is a link file!" << endl;

    cout << "The size of the file is " << buf.st_size << endl; 

//获取文件的修改,创建等时间
    printf("atime = %d, mtime = %d, ctime = %d\n",buf.st_atime, buf.st_mtime, buf.st_ctime);

    struct tm *pt = gmtime(&(buf.st_atime));
    printf("%4d-%02d-%02d    %02d:%02d:%02d\n", (1900+pt->tm_year), (1+pt->tm_mon), pt->tm_mday,(8+pt->tm_hour), pt->tm_min, pt->tm_sec);//小时差8,月份差1,年差1900

    return 0;
}