二、标准I/O和文件I/O

1. 标准IO介绍及缓冲区

  • Linux IO 进程课程目的:学习编写 linux 应用程序(APP)

  • Linux 文件的种类 :
    常规文件 r
    目录文件 d
    字符文件 c
    块文件 b
    链接文件(相当于 windows 快捷方式)l
    socket文件 s
    管道文件 p

  • IO 的概念
    I input: 输入设备 比如键盘鼠标都是 Input 设备
    O output 输出设备 比如显示器
    优盘,网口,既是输入也是输出

  • 系统调用和库函数
    系统调用就是操作系统提供的接口函数.
    如果我们把系统调用封装成库函数就可以起到隔离的作用,提供程序的可移植性。
    Printf 就是库函数然后调用了系统调用才在显示器上显示字符

  • 流的概念
    就是数据的流,在程序中就是一个结构体。

  • Windows 和 linux 的换行符区别
    Windows 是\r\n
    Linux 是\n

  • 缓冲区的概念
    为了减少操作 IO 设备的次数,提高运行效率,在内存里面设置的缓冲区,
    全缓冲:缓冲区满才输出
    行缓冲:遇到换行符输出

  • 三种标准 IO :


  • 缓冲区概念演示:
    程序正常结束会刷新缓冲区

#include<stdio.h>
int main(int argc, char* argv[]){

    printf("hello world");
    return 0;
}
  • Sleep 函数:是释放 cpu 给其他应用程序使用的库函数。使用的头文件是#include<unistd.h>
    查看头文件方法:man 2 函数 ,或者 man 3 函数
#include<stdio.h>
#include<unistd.h>
int main(int argc, char* argv[]){
    printf("hello world");
    while(1){
      sleep(1);
    }
    return 0;
}

结果无任何输出,因为缓冲区未满也没\n, 程序也没结束。

2. 标准IO: 文件的打开和关闭

文件的打开和关闭概念

打开就是占用资源
关闭就是释放资源

文件的打开

  • 文件的打开函数
    FILE *fopen (const char *path, const char *mode);
    Path: 普通文件当前路径不需要加目录,其他要使用完整的路径
    Mode:
    返回值:出错返回 NULL,所以使用 fopen 函数必须判断是否为空

  • 文件打开的模式(非常重要)


  • 编译错误:
    f_open.c:9:38: error: ‘errno’ undeclared (first use in this function)
    printf("fopen:%s\n",strerror(errno));
    error: ‘errno’ undeclared 表示 errno 变量没有定义
    解决方法:如果是系统变量用 include 头文件,如果是你自己的,自己手动定义。
    f_open.c:10:29: warning: implicit declaration of function ‘strerror’
    [-Wimplicit-function-declaration]
    printf("fopen:%s\n",strerror(errno));
    warning: implicit declaration of function ‘strerror’ 表示 strerror 函数隐示的声明
    解决方法:include 添加对应的头文件。

  • perror 库函数 头文件 stdio.h
    strerror 库函数 头文件 errno.h string.h
    perror 和 strerror 功能:打印系统的错误描述(注意:是系统错误,不是你自己代码错误)

文件的关闭:

函数原型:int fclose(FILE *stream)

  • fclose()调用成功返回 0,失败返回 EOF(-1),并设置 errno
  • 流关闭时自动刷新缓冲中的数据并释放缓冲区,比如:常规文件把缓冲区内容写入磁盘
  • 当一个程序正常终止时,所有打开的流都会被关闭
  • fclose()函数的入参 stream 必须保证为非空,否则出现断错误。
#include<stdio.h>
#include<string.h>
#include<errno.h>

int main(int argc, char * argv[]){
    FILE *fp = fopen("1.txt","r");
    int fret = EOF;
    if(fp == NULL){
      perror("fopen");
      printf("fopen: %s\n",strerror(errno));
    }else{
      printf("fopen: open file success\n");
      fret = fclose(fp);
      if(fret == 1){
         printf("file close success\n");
      }else{
         perror("fclose");
      }
    }
  return 1;
}

3. 标准 IO 的字符输入和输出

字符的输入(读单个字符)

int fgetc(FILE *stream);
int getc(FILE *stream); //宏
int getchar(void);
成功时返回读取的字符;若到文件末尾或出错时返回 EOF(-1),
getchar()等同于 fgetc(stdin)
getc 和 fgetc 区别是一个是宏一个是函数

注意事项:

  1. 函数返回值是 int 类型不是 char 类型,主要是为了扩展返回值的范围。(char范围是-128 -- 127 unsigned char 0 - 255, int就都包含了)
  2. stdin 也是 FILE *的指针,是系统定义好的,指向的是标准输入(键盘输入)
  3. 打开文件后读取,是从文件开头开始读。读完一个后读写指针会后移。读写注意文件位置!
  4. 调用 getchar 会阻塞,等待你的键盘输入

字符的输出(写单个字符):

int fputc(int c, FILE *stream);
int putc(int c, FILE *stream);
int putchar(int c);

成功时返回写入的字符;出错时返回 EOF
putchar(c)等同于 fputc(c, stdout)

行输入(读取整个行)

char *gets(char *s); 读取标准输入到缓冲区 s
char *fgets(char *s, int size, FILE *stream);
成功时返回 s,到文件末尾或出错时返回 NULL
遇到’\n’或已输入 size-1 个字符时返回,总是包含’\0’

注意事项:

  1. gets 函数已经被淘汰,因为会导致缓冲区溢出
  2. fgets 函数第二个参数,输入的数据超出 size,size-1 个字符会保存到缓冲区,最后添加’\0’,如果输入数据少于 size-1 后面会添加换行符。

行输出(写整行)

int puts(const char *s);
int fputs(const char *s, FILE *stream);

  • 成功时返回非负整数;出错时返回 EOF
  • puts 将缓冲区 s 中的字符串输出到 stdout,并追加’\n’
  • fputs 将缓冲区 s 中的字符串输出到 stream,不追加 ‘\n’

4. 标准IO读写:二进制方式

文本文件和二进制的区别:
存储的格式不同:文本文件只能存储文本。
计算机内码概念:文本符号在计算机内部的编码(计算机内部只能存储数字 0101001....,所以所有符号都要编码)

二进制读写函数格式:
size_t fread(void *ptr, size_t size, size_t n, FILE *fp);
void *ptr 读取内容放的位置指针
size_t size 读取的块大小
size_t n 读取的个数
FILE *fp 读取的文件指针

size_t fwrite(const void *ptr, size_t size, size_t n, FILE *fp);
void *ptr 写文件的内容的位置指针
size_t size 写的块大小
size_t n 写的个数
FILE *fp 要写的文件指针

fread: 从1.txt中读出10个字符

#include<stdio.h>
#include<stdlib.h>
int main(){
    FILE *fp;
    size_t ret;
    char* buff;
    fp = fopen("1.txt","r");
    if(fp == NULL){
       perror("fopen");
       return -1;
    }
    buff = (char *)malloc(100);
    if(buff == NULL){
       perror("buff");
       fclose(fp);
       return -1;
    }

    ret = fread(buff,10,1,fp);
    if(ret == EOF){
       perror("fread");
       goto end;
    }
    printf("ret = %s\n",buff);
end:
    free(buff);
    fclose(fp);
    return 0;
}

fwrite: 往1.bin中写入1个struct Student对象的二进制

#include<stdio.h>
#include<string.h>
struct Student{
  char name[16];
  int age;
  char sex[8];
};
int main(){

    FILE *fp;
    size_t ret;
    fp = fopen("1.bin","w");
    if(fp == NULL){
       perror("fopen");
       return -1;
    }

    struct Student stu;
    strcpy(stu.name,"zhangsan");
    stu.age = 18;
    strcpy(stu.sex,"male");

    ret = fwrite(&stu,sizeof(stu),1,fp);
    if(ret == EOF){
        perror("fwrite");
        goto end;
    }
end:
    fclose(fp);
    return 0;
}
#include<stdio.h>
#include<string.h>
struct Student{
  char name[16];
  int age;
  char sex[8];
};
int main(){

    FILE *fp;
    size_t ret;
    struct Student stu;
    struct Student stu2;
    fp = fopen("1.bin","w");
    if(fp == NULL){
       perror("fopen");
       return -1;
    }

    strcpy(stu.name,"zhangsan");
    stu.age = 18;
    strcpy(stu.sex,"male");

    ret = fwrite(&stu,sizeof(stu),1,fp);
    if(ret == EOF){
        perror("fwrite");
        goto end;
    }else{
      printf("write student success\n");
    }

    ret = fread(&stu2,sizeof(stu2),1,fp);
    if(ret == EOF){
       perror("fread");
       goto end;
    }
    printf("stu2.name=%s,stu2.age=%d,stu2.sex=%s\n",stu2.name,stu2.age,stu2.sex);
end:
    fclose(fp);
    return 0;
}
输出:stu2.name=,stu2.age=0,stu2.sex=

注意事项:

文件写完后,文件指针指向文件末尾,如果这时候读,读不出来内容。
解决办法:移动指针(后面讲解)到文件头;或关闭文件,重新打开

5. 流刷新定位

流的刷新

int fflush(FILE *fp);

  • 成功时返回 0;出错时返回 EOF
  • 将流缓冲区中的数据写入实际的文件
  • Linux 下只能刷新输出缓冲区,输入缓冲区丢弃
  • 如果输出到屏幕使用 fflush(stdout)
#include<stdio.h>
#include<unistd.h>
int main(){
    printf("abcdefghijklmn");
    fflush(stdout); //不加这一行将无法输出 因为缓冲区未满也没\n, 程序也没结束。
    while(1){
      sleep(1);
    }
    return 0;
}
#include<stdio.h>
#include<unistd.h>
int main(){
    FILE *fp;
    size_t ret;
    fp = fopen("fflush.txt","w");
    if(fp == NULL){
        perror("fopen");
        return -1;
    }

    ret = fwrite("abcdefghigklmn",14,1,fp);
    if(ret == EOF){
      perror("fwrite");
    }
    fflush(fp); //不加这一行 也无法将内容写入到文件

    while(1){
      sleep(1);
    }
    return 0;
}

流的定位

#include <stdio.h>
long ftell(FILE *stream);
long fseek(FILE *stream, long offset, int whence);
void rewind(FILE *stream);

  • ftell() 成功时返回流的当前读写位置,出错时返回 EOF
  • fseek() 定位一个流,成功时返回 0 ,出错时返回 EOF
  • whence 参数: SEEK_SET/SEEK_CUR/SEEK_END
  • SEEK_SET 从距文件开头 offset 位移量为新的读写位置
  • SEEK_CUR :以目前的读写位置往后增加 offset 个位移量
  • SEEK_END :将读写位置指向文件尾后再增加 offset 个位移量
  • offset 参数:偏移量,可正可负
  • 打开 a 模式 fseek 无效
  • rewind() 将流定位到文件开始位置
  • 读写流时,当前读写位置自动后移
  • 注意事项:
    1.文件的打开使用 a 模式 fseek 无效
    2.rewind(fp) 相当于 fseek(fp,0,SEEK_SET);
    3.这三个函数只适用 2G 以下的文件
#include<stdio.h>

int main(){
    FILE *fp;
    fp = fopen("1.txt","w");
    if(fp == NULL){
        perror("fopen");
        return 0;
    }

    fwrite("abcdefg",7,1,fp);
    printf("current fp=%d\n",(int)ftell(fp));
    rewind(fp);
    printf("after fp=%d\n",(int)ftell(fp));

    return 0;
}

int ferror(FILE *stream);
int feof(FILE *stream);

  • ferror() 返回 1 表示流出错;否则返回 0
  • feof() 返回 1 表示文件已到末尾;否则返回 0

6. 格式化输入输出

格式化输出

int printf(const char *fmt, …);
int fprintf(FILE *stream, const char *fmt, …);
int sprintf(char *s, const char *fmt, …);

  • 成功时返回输出的字符个数;出错时返回 EOF
#include<stdio.h>

int main(){

    FILE *fp;
    size_t ret;
    int year = 2025;
    int month = 8;
    int day = 1;
    fp = fopen("1.txt","w");
    if(fp == NULL){
        perror("fopen");
        return 0;
    }

    ret = fprintf(fp,"%d-%d-%d",year,month,day);
    if(ret == EOF){
        perror("fprintf");
    }
    fclose(fp);
    return 0;
#include<stdio.h>

int main(){
    char buff[20]={0};
    size_t ret;
    int year = 2025;
    int month = 8;
    int day = 1;
    ret = sprintf(buff,"%d-%d-%d",year,month,day);
    if(ret == -1){
        perror("sprintf");
    }
    printf("%ld %s",ret,buff);
    return 0;
}

格式化输入

int fscanf(FILE *stream, const char *format, ...);
int sscanf(const char *str, const char *format, ...);

  • 成功时返回输出的字符个数;出错时返回 EOF
#include<stdio.h>

int main(){
    FILE *fp;
    int year, month, day;
    fp = fopen("1.txt","r");
    if(fp == NULL){
        perror("fopen");
        return 0;
    }
    fscanf(fp,"%d-%d-%d",&year,&month,&day);
    printf("%d-%d-%d\n",year, month, day);
    fclose(fp);
    return 0;
}
#include<stdio.h>

int main(){
    char buff[20]={0};
    size_t ret;
    int year = 2025;
    int month = 8;
    int day = 1;
    int syear, smonth, sday;
    ret = sprintf(buff,"%d-%d-%d",year,month,day);
    if(ret == -1){
        perror("sprintf");
    }
    printf("%ld %s\n",ret,buff);
    sscanf(buff,"%d-%d-%d",&syear,&smonth,&sday);
    printf("%d-%d-%d\n",syear,smonth,sday);
    return 0;
}

7. 标准IO练习

  • 每隔 1 秒向文件 test.txt 中写入当前系统时间,格式如下:
    1, 2014-10-15 15:16:42
    2, 2014-10-15 15:16:43
    该程序无限循环,直到按 Ctrl-C 中断程序
    每次执行程序时,系统时间追加到文件末尾,序号递增
    1, 2014-10-15 15:16:42
    2, 2014-10-15 15:16:43
    3, 2014-10-16 11:35:07
    4, 2014-10-16 11:35:08

time() 用来获取系统时间 ( 秒数 )
time_t time(time_t *seconds) 1970.1.1 0:0:0
localtime() 将系统时间转换成本地时间
struct tm *localtime(const time_t timer)
struct tm {
int tm_sec; /
秒,范围从 0 到 59 /
int tm_min; /
分,范围从 0 到 59 /
int tm_hour; /
小时,范围从 0 到 23 /
int tm_mday; /
一月中的第几天,范围从 1 到 31 /
int tm_mon; /
月份,范围从 0 到 11 /
int tm_year; /
自 1900 起的年数 /
int tm_wday; /
一周中的第几天,范围从 0 到 6 /
int tm_yday; /
一年中的第几天,范围从 0 到 365 /
int tm_isdst; /
夏令时 */
};

#include<stdio.h>
#include<unistd.h>
#include<time.h>
#include<string.h>
#include<errno.h>
int main(){
    FILE *fp;
    time_t ctime;
    struct tm *ctimestr;
    int line_num = 0;
    char buff[32] = {};
    fp = fopen("time.txt","a+");
    if(fp == NULL){
        perror("fopen");
        return -1;
    }

    while(fgets(buff,32,fp) != NULL){
        if(buff[strlen(buff)-1] == '\n')
            line_num++;
    }

    while(1){
        ctime = time(NULL);
    //  printf("current time:%ld",ctime);
      ctimestr = localtime(&ctime);
      printf("%04d-%02d-%02d %02d:%02d:%02d\n",ctimestr->tm_year+1900,ctimestr->tm_mon+1,
              ctimestr->tm_mday, ctimestr->tm_hour,ctimestr->tm_min,ctimestr->tm_sec);
     
      fprintf(fp,"%d %04d-%02d-%02d %02d:%02d:%02d\n",line_num,ctimestr->tm_year+1900,ctimestr->tm_mon+1,
              ctimestr->tm_mday, ctimestr->tm_hour,ctimestr->tm_min,ctimestr->tm_sec);
      fflush(fp);
      line_num++;
      sleep(1);
    }
    fclose(fp);
    return 0;
}

8. 文件I/O

什么是文件 I/O ?
posix( 可移植操作系统接口 ) 定义的一组函数
不提供缓冲机制,每次读写操作都引起系统调用


文件I/O

文件描述符

  • 每个打开的文件都对应一个文件描述符。
  • 文件描述符是一个非负整数。 Linux 为程序
    中每个打开的文件分配一个文件描述符。
  • 文件描述符从 0 开始分配,依次递增。
  • 文件 IO 操作通过文件描述符来完成。
  • 0, 1, 2 的含义?

open

open 函数用来创建或打开一个文件 :
#include <fcntl.h>
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t
mode);
成功时返回文件描述符;出错时返回 EOF
打开文件时使用两个参数
创建文件时第三个参数指定新文件的权限,(只有在建立
新文件时有效)此外真正建文件时的权限会受到 umask
值影响,实际权限是 mode-umaks
可以打开设备文件,但是不能创建设备文件




open示例1:

#include<stdio.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
int main(){
   int fd;
   fd = open("1.txt",O WRONLY|O CREATIO TRUNC,0666);
   if(fd<0){
   perror("open");
   return 0;
   }
   return 0;
}

open示例2:

#include<stdio.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
int main(){
  int fd;
  fd = open("1.txt",O_WRONLY|O_CREAT|O_EXCL);
  if(fd < 0){
    if(errno == EEXSIT){
        perror("exist error");
     }else{
        perror("other error");
     }
     return 0;
  }
  return 0;
}

close

close 函数用来关闭一个打开的文件 :
#include <unistd.h>
int close(int fd);

  • 成功时返回 0 ;出错时返回 EOF
  • 程序结束时自动关闭所有打开的文件
  • 文件关闭后,文件描述符不代表任何文件
#include<stdio.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
int main(){
    int ret;
    int fd;
    fd = open("1.txt",O_WRONLY|O_CREAT|O_TRUNC,0666);
    if(fd<0){
        perror("open file error");
        return 0;
    }
    printf("fd=%d\n",fd);
    ret = close(fd);
    if(ret < 0){
      perror("close");
    }
    return 0;
}

read

#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);

  • 成功时返回实际读取的字节数;出错时返回 EOF
  • 读到文件末尾时返回 0
  • buf 是接收数据的缓冲区
  • count大小不应超过buf长度
#include<stdio.h>
#include<errno.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
int main(int argc, char *argv[]){
    int fd, n, total;
    char buf[64] = {};
    if(argc < 2){
      printf("usage file:%s\n",argv[0]);
      return -1;
    }
    fd = open(argv[1],O_RDONLY);
    if(fd < 0){
      perror("open");
      return 0;
    }
    while((n = read(fd,buf,64)) > 0){
       total += n;
    }
    printf("file total:%d\n",total);
    
    return 0;
}

write

write 函数用来向文件写入数据 :
#include <unistd.h>
ssize_t write(int fd, void *buf, size_t count);

  • 成功时返回实际写入的字节数;出错时返回 EOF
  • buf 是发送数据的缓冲区
  • count不应超过buf大小
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<fcntl.h>
#include<errno.h>
#include<string.h>
int main(){

    int fd;
    char buf[20];
    fd = open("1.txt",O_WRONLY|O_CREAT|O_TRUNC,0664);
    if(fd < 0)
    {
        perror("open");
        return -1;
    }

    while(fgets(buf,20,stdin) != NULL){
        if(strcmp(buf,"quite\n") == 0)
            break;
        write(fd,buf,strlen(buf));
    }
        close(fd);
    return 0;
}

lseek

lseek 函数用来定位文件 :
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);

  • 成功时返回当前的文件读写位置;出错时返回 EOF
  • 参数offset和参数whence同fseek
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<errno.h>
#include<string.h>
int main(){
   int fd, ret;
   char buf[32] = "hello world";
   char buf2[32] = {0};
   fd = open("test.h", O_RDWR | O_CREAT | O_APPEND,0666);
   if(fd < 0){
      perror("open");
      return -1;
   }

   ret = write(fd,buf, strlen(buf));
   if(ret < 0){
       perror("write");
       goto END;
   }
   ret = lseek(fd,0,SEEK_SET);
   if(ret == EOF){
       perror("lseek");
       goto END;
   }

   ret = read(fd,buf2,32);
   if(ret < 0){
       perror("read");
       goto END;
   }
   buf2[31] = '\0';
   printf("buf2:%s\n",buf2);
END:
   close(fd);
   return 0;
}

9. 目录操作、文件属性

访问目录 – opendir

opendir 函数用来打开一个目录文件 :
#include <dirent.h>
DIR *opendir(const char *name);
DIR *fdopendir(int fd); 使用文件描述符,要配合 open 函数使用

  • DIR 是用来描述一个打开的目录文件的结构体类型
  • 成功时返回目录流指针,出错时返回NULL

访问目录 – readdir

readdir 函数用来读取目录流中的内容 :
#include <dirent.h>
struct dirent *readdir(DIR *dirp);

  • struct dirent 是用来描述目录流中一个目录项的结构体类型
  • 包含成员 char d_name[256] 参考帮助文档
  • 成功时返回目录流 dirp 中下一个目录项;
  • 出错或到末尾返回NULL

访问目录 – closedir

closedir 函数用来关闭一个目录文件 :
#include <dirent.h>
int closedir(DIR *dirp);

  • 成功时返回0 错误返回EOF

访问目录 – 示例代码

#include<stdio.h>
#include<errno.h>
#include<dirent.h>

int main(int argc, char *argv[]){

    DIR *dirp;
    struct dirent *dp;
    int ret;
    if(argc < 2){
       printf("usage:%s<directory>\n",argv[0]);
    }
    dirp = opendir(argv[1]);
    if(dirp == NULL){
       perror("opendir");
       return -1;
    }

    while((dp = readdir(dirp)) != NULL){
        printf("%s\n",dp->d_name);
    }
    ret = closedir(dirp);
    if(ret < 0){
      perror("closedir");
    }
    return 0;
}

修改文件访问权限 – chmod/fchmod

chmod/fchmod 函数用来修改文件的访问权限 :
#include <sys/stat.h>
int chmod(const char *path, mode_t mode);
int fchmod(int fd, mode_t mode);

  • 成功时返回 0 ;出错时返回 EOF
  • root 和文件所有者能修改文件的访问权限
#include<stdio.h>
#include<sys/stat.h>
#include<errno.h>
int main(int argc, char *argV[])
{
    int ret;
    ret = chmod("readdir_t",0444);
    if(ret == EOF){
       perror("chmod");
       return -1;
    }
    return 0;
}

获取文件属性 – stat/lstat/fstat

stat/lstat/fstat 函数用来获取文件属性 :
#include <sys/stat.h>
int stat(const char *path, struct stat *buf);
int lstat(const char *path, struct stat *buf);
int fstat(int fd, struct stat *buf);

  • 成功时返回 0;出错时返回 EOF
  • 如果 path 是符号链接 stat 获取的是目标文件属性;而lstat是获取的链接文件的属性

文件属性 – struct stat

struct stat 是存放文件属性的结构体类型 :

  • mode_t st_mode; 类型和访问权限
  • uid_t st_uid; 所有者 id
  • uid_t st_gid; 用户组 id
  • off_t st_size; 文件大小
  • time_t st_mtime; 最后修改时间
• struct stat {
• dev_t st_dev; // 文件的设备编号
• ino_t st_ino; // 节点
• mode_t st_mode; // 文件的类型和存取的权限
• nlink_t st_nlink; // 连到该文件的硬连接数目,刚建立的文件值为 1
• uid_t st_uid; // 用户 ID
• gid_t st_gid; // 组 ID
• dev_t st_rdev; //( 设备类型 ) 若此文件为设备文件,则为其设备编号
• off_t st_size; // 文件字节数 ( 文件大小 )
• unsigned long st_blksize; // 块大小 ( 文件系统的 I/O 缓冲区大小 )
• unsigned long st_blocks; // 块数
• time_t st_atime; // 最后一次访问时间
• time_t st_mtime; // 最后一次修改时间
• time_t st_ctime; // 最后一次改变时间 ( 指属性 )
};

文件类型 – st_mode

通过系统提供的宏来判断文件类型 :
S_IFMT 0170000 文件类型的位遮罩
S_ISREG(st_mode) 0100000 是否常规文件
S_ISDIR(st_mode) 0040000 是否目录
S_ISCHR(st_mode) 0020000 是否字符设备
S_ISBLK(st_mode) 0060000 是否块设备
S_ISFIFO(st_mode) 0010000 是否 FIFO 文件
S_ISLNK(st_mode) 0120000 是否链接文件
S_ISSOCK(st_mode)) 0140000 是否socket文件

文件访问权限 – st_mode

通过系统提供的宏来获取文件访问权限 :
S_IRUSR 00400 bit:8 所有者有读权限
S_IWUSR 00200 7 所有者拥有写权限
S_IXUSR 00100 6 所有者拥有执行权限
S_IRGRP 00040 5 群组拥有读权限
S_IWGRP 00020 4 群组拥有写权限
S_IXGRP 00010 3 群组拥有执行权限
S_IROTH 00004 2 其他用户拥有读权限
S_IWOTH 00002 1 其他用户拥有写权限
S_IXOTH 00001 0 其他用户拥有执行权限

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 标准I/O:数据从内存与标准i/o设备(stdio,stdout,stderr)之间的数据流动 文件I/O:文件的...
    FakeCSer爱去网吧阅读 103评论 0 0
  • 在该章节中讨论的文件描述符的概念。其中包括:打开文件,关闭文件,从文件中读取数据和向文件中写数据。 概述所有执行I...
    Capr1corn阅读 998评论 0 0
  • 1.1 C标准函数与系统函数 C标准是工作在操作系统之上的。比如要执行C标准函数printf函数,printf会调...
    FlyingReganMian阅读 1,132评论 0 0
  • IO是一个比较大的概念,它所涉及到的内容也比较多,比较繁杂,下面就从文件的IO开始说起,因为unix下,一切皆文件...
    飞翃荷兰人阅读 830评论 0 0
  • 所有执行I/O操作的系统调用都以文件描述符(一个非负整数)来指代打开的文件。包括pipe,FIFO,socket,...
    loopppp阅读 757评论 0 0

友情链接更多精彩内容