文件读写——获取文件属性

文件读写——获取文件属性以下内容源于朱有鹏嵌入式课程的学习整理与整理 如有侵权请告知删除

大家好,欢迎来到IT知识分享网。

以下内容源于朱有鹏嵌入式课程的学习整理与整理,如有侵权请告知删除。

前言

文件属性,包括文件的名字、创建时间、文件类型、文件权限等等内容。

本文讲述了以下内容:

(1)文件类型有哪些;

(2)文件权限管理的内容;

(3)利用stat函数获取某个文件的属性信息;

(4)操作目录文件。

一、文件类型

文件类型 符号标识
普通文件 (regular file)
目录文件(directory) d
字符设备文件(character) c
块设备文件(block) b
管道文件(pipe) p
套接字文件(socket) s
符号链接文件(link) l

1、普通文件

1)普通文件包括:文本文件、二进制文件。

文本文件,是由ASCII码字符构成的文件。常见的.c文件、.h文件、.txt文件等都是文本文件,它可以被人轻松读懂和编写,是为人类而发明的。其实文本文件本质上还是由数字01构成的文件,不过编辑器读出这些数字后,按照编码格式转化成ASCII字符。

二进制文件,是有01数字构成的文件,不过01数字不是某些字符的编码,而是真正的数字。常见的可执行程序文件,比如由gcc编译生成的a.out、arm-linux-gcc编译连接生成的.bin文件,都是二进制文件。

2)如何区别二进制文件和文本文件?

从本质上来看,文本文件和二进制文件并没有任何区别,都是一个文件里面存放了数字。如果把这些数字就当作数字处理则就是二进制文件,如果把这些数字按照某种编码格式去解码成文本字符,则就是文本文件。

Linux系统不区分这两种文件,比如open、read、write等方法操作文本文件和二进制文件时,没有一点区分。为了明确文件类型,有时候人为地添加后缀来表征文件类型。

3)如何打开与编辑?

常见的文本文件编辑器如vim、gedit、notepad++、SourceInsight等;使用这些文本文件编辑器去打开文件的时候,编辑器读出文件二进制数字内容,然后按照编码格式去解码将其还原成文字。

如果用文本文件编辑器去打开一个二进制文件,编辑器以为这个二进制文件还是文本文件,然后试图去将其解码成文字,但是解码过程很多数字并不对应有意义的文字,所以成了乱码。

如果用二进制阅读工具去读取文本文件,得到的就是文本文字所对应的二进制的编码。

2、目录文件

目录文件即文件夹,文件夹在linux中也是一种文件,不过是特殊文件。

用vi打开一个文件夹,可知文件夹里的内容包括这个文件夹的路径、文件夹里面的文件列表。

linux中使用特殊的一些API读写文件夹。

3、块设备文件

设备文件对应的是硬件设备。

它不是真正存在于硬盘上的一个文件,而是由文件系统虚拟制造出来的。

虚拟文件系统中的文件,需要用一些特殊的API产生或者使用。

二、文件权限

文件权限,指不同用户的读写与执行权限。

1、“ls -l”命令

使用“ls -l”命令打印出来的信息,比如“- rwx rwx rwx”,其中“-”表示文件类型(这里表示普通文件);从左到右,第一组“rwx”表示文件属主对该文件的操作权限,第二组表示文件属主所在组队该文件的操作权限,第三组表示其他用户对该文件的操作权限。

2、access函数

函数原型

 int access(const char *pathname, int mode);

函数作用

该函数用来检测当前用户对文件是否具有某种操作权限。

补充说明

mode的可取值分别为:R_OK、W_OK、X_OK、F_OK。它们分别用来测试是否可读、是否可写、是否可执行、文件是否存在。 

3、chmod函数

只有root用户才能使用chmod命令,该命令实际调用的是Linux内部一个叫做chmod的API。

函数原型

int chmod(const char *path, mode_t mode);

函数作用

该函数用来修改文件的权限

补充说明

(1)chmod命令的细节:chmod命令:修改文件(夹)权限_天糊土的博客-CSDN博客

(2)mode的可选值及其含义

S_IRUSR  (00400)  read by owner

S_IWUSR  (00200)  write by owner

S_IXUSR  (00100)  execute/search  by  owner (“search” applies for directories, and means that entries within the directory can be accessed)

S_IRGRP  (00040)  read by group

S_IWGRP  (00020)  write by group

S_IXGRP  (00010)  execute/search by group

S_IROTH  (00004)  read by others

S_IWOTH  (00002)  write by others

S_IXOTH  (00001)  execute/search by others

代码示例

ret=chmod(argv[1] ,S_IRUSR | S_IWUSR | S_IXUSR)

三、获取文件属性

1、stat函数的介绍

每个文件都具有一些属性(比如文件类型、文件权限等等),这些属性存在于文件本身,只能被一些专用的API打开看到,比如stat、fstat、lstat,它们作用一样,参数不同,细节略有不同。这里重点简述stat这个API。

在命令行中,使用命令“man 1 stat”以及“man 2 stat”,都可以得到stat的使用手册。这说明stat是linux下的一个命令,同时也是linux下的API(或者说函数),或者说stat命令就是通过stat这个API来实现的。

xjh@ubuntu:~/iot/tmp$ stat sample.c File: ‘sample.c’ Size: 169 Blocks: 8 IO Block: 4096 regular file Device: 801h/2049d Inode:  Links: 1 Access: (0664/-rw-rw-r--) Uid: ( 1000/ xjh) Gid: ( 1000/ xjh) Access: 2022-06-17 23:47:02. +0800 Modify: 2022-06-17 23:29:15. +0800 Change: 2022-06-17 23:29:15. +0800 Birth: - xjh@ubuntu:~/iot/tmp$ //上面的IO BLOCK 表示达到多少内容时,缓冲区的内容才会写入硬盘 

stat函数的模型

 int stat(const char *path, struct stat *buf);

stat函数的作用

内核将某个文件的属性信息结构体填充到stat函数的参数buf所指向的结构体中(这个参数是不加const修饰的指针,说明它是输出型参数),当stat这个API调用从内核返回时,buf所指向的结构体就被文件的属性信息填充好了。

我们后续通过查看buff结构体变量的元素,就可以得知该文件的各种属性。比如:

#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #define NAME "1.txt" //这样写的时候,注意该程序的路径是在该文件的同路径下 int main(void) { int ret = -1; struct stat buf; //struct stat buf={0};初始化方法1,或者使用下面的 memset(&buf, 0, sizeof(buf)); // memset后buf中全是0 ret = stat(NAME, &buf); // stat后buf中有内容了 if (ret < 0) { perror("stat"); exit(-1); } // 成功获取了stat结构体,从中可以得到各种属性信息了 printf("inode = %d.\n", buf.st_ino); printf("size = %d bytes.\n", buf.st_size); printf("st_blksize = %d.\n", buf.st_blksize); return 0; }

参数说明

struct stat是内核定义的一个结构体,在<sys/stat.h>中声明。 这个结构体中的所有元素加起来就是文件属性信息。

 struct stat { dev_t st_dev; /* ID of device containing file */ ino_t st_ino; /* inode number */ mode_t st_mode; /* protection */ nlink_t st_nlink; /* number of hard links */ uid_t st_uid; /* user ID of owner */ gid_t st_gid; /* group ID of owner */ dev_t st_rdev; /* device ID (if special file) */ off_t st_size; /* total size, in bytes */ blksize_t st_blksize; /* blocksize for filesystem I/O */ blkcnt_t st_blocks; /* number of 512B blocks allocated */ time_t st_atime; /* time of last access */ time_t st_mtime; /* time of last modification */ time_t st_ctime; /* time of last status change */ }; 

补充说明

stat和stat的区别

  • stat是从文件名出发得到文件属性信息结构体,而fstat是从一个已经打开的文件fd出发,得到一个文件的属性信息;
  • 如果文件没有打开就用stat,如果文件已经被打开用fstat效率会更高。因为stat是从磁盘去读取文件的,而fstat是从内存读取动态文件的。

lstat和stat/fstat的差别

  • 对于符号链接文件,stat和fstat查阅的是符号链接文件指向的文件的属性,而lstat查阅的是符号链接文件本身的属性。

2、stat函数的应用案例

(1)获知文件类型

文件类型标志在struct stat结构体的 st_mode 元素中。

  • st_mode本质上是一个32位的数(类型就是unsinged int),这个数里的每一个位表示一个含义,按位&操作可以知道某些信息。
  • 但是这些位定义不容易记住,因此linux系统事先定义很多宏来进行相应操作。
  • 比如S_ISREG宏返回值是1表示这个文件是一个普通文件,如果文件不是普通文件则返回值是0;
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)? S_ISLNK(m) symbolic link? (Not in POSIX.1-1996.) S_ISSOCK(m) socket? (Not in POSIX.1-1996.) 

2)获知文件权限

st_mode中除了记录文件类型,还记录着一个重要信息:文件权限。

linux并没有给文件权限测试提供宏操作,只提供了位掩码,所以我们只能用位掩码来判断是否具有相应权限。

 The following flags are defined for the st_mode field: S_IFMT 0 bit mask for the file type bit fields S_IFSOCK 0 socket S_IFLNK 0 symbolic link S_IFREG 0 regular file S_IFBLK 0060000 block device S_IFDIR 0040000 directory S_IFCHR 0020000 character device S_IFIFO 0010000 FIFO S_ISUID 0004000 set-user-ID bit S_ISGID 0002000 set-group-ID bit (see below) S_ISVTX 0001000 sticky bit (see below) S_IRWXU 00700 mask for file owner permissions S_IRUSR 00400 owner has read permission S_IWUSR 00200 owner has write permission S_IXUSR 00100 owner has execute permission S_IRWXG 00070 mask for group permissions S_IRGRP 00040 group has read permission S_IWGRP 00020 group has write permission S_IXGRP 00010 group has execute permission S_IRWXO 00007 mask for permissions for others (not in group) S_IROTH 00004 others have read permission S_IWOTH 00002 others have write permission S_IXOTH 00001 others have execute permission 

3)代码示例

#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #define NAME "1.txt" int main(void) { int ret = -1; struct stat buf; memset(&buf, 0, sizeof(buf)); // memset后buf中全是0 ret = stat(NAME, &buf); // stat后buf中有内容了 if (ret < 0) { perror("stat"); exit(-1); } #if 0 // 判断这个文件属性 int result = S_ISDIR(buf.st_mode); printf("result = %d\n", result); #endif // 文件权限测试 unsigned int result = ((buf.st_mode & S_IRUSR)? 1: 0); printf("file owner: %u.\n", result); return 0; }

三、对目录文件的操作

(1)opendir函数与readdir函数

对于目录文件,我们一般先使用opendir函数打开目录文件,然后再使用readdir函数读取目录文件。

在命令行中输入“man 3 opendir”、“man 3readdir”,可以知道这两个函数的模型:

DIR *opendir(const char *name); 
struct dirent *readdir(DIR *dirp);

使用opendir函数打开一个目录后,得到一个DIR类型的指针给readdir使用。

每调用一次readdir函数,就会返回一个struct dirent类型的指针,它记录着目录中的一个文件。要想读出目录中所有的文件,必须多次调用readdir函数。当readdir函数返回NULL时就表示目录中所有的文件都已经被读完了。另外,readdir函数内部户会对已经读过的文件进行记录,因此不会重复返回已经返回过的文件。

(2)struct dirent 结构体

struct dirent { ino_t d_ino; /* inode number */ off_t d_off; /* not an offset; see NOTES */ 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]; /* filename */ }; 

(3)代码示例

将下面的代码用gcc编译生成a.out文件,然后在命令行输入“./a.out xxx”,其中xxx表示某个目录。

#include <stdio.h> #include <sys/types.h> #include <dirent.h> int main(int argc, char argv) { DIR *pDir = NULL; struct dirent * pEnt = NULL; unsigned int cnt = 0; if (argc != 2) { printf("usage: %s dirname\n", argv[0]); return -1; } pDir = opendir(argv[1]); if (NULL == pDir) { perror("opendir"); return -1; } while (1) { pEnt = readdir(pDir); if(pEnt != NULL) { // 还有子文件,在此处理子文件 printf("name:[%s] ,", pEnt->d_name); cnt++; if (pEnt->d_type == DT_REG) { printf("是普通文件\n"); } else { printf("不是普通文件\n"); } } else { break; } }; printf("总文件数为:%d\n", cnt); return 0; }

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/120900.html

(0)
上一篇 2025-10-26 19:26
下一篇 2025-10-26 19:45

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信