Java教程

文件和目录

本文主要是介绍文件和目录,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

大纲

    • 目录和文件
      • 获取文件属性
        • stat函数
        • 返回值
      • 文件访问权限
      • umask
      • 文件权限更改:chmod、fchmod
      • 粘着位(t位)
      • 文件系统:FAT、UFS
      • 硬链接和符号链接
      • 目录的创建和销毁:mkdir、rmdir(只能删除空目录)
      • 更改当前工作路径
      • 分析目录/读取目录内容
        • glob
        • 返回值
        • 使用样例
        • 使用目录相关函数
          • opendir、closedir
          • readdir

目录和文件

获取文件属性

stat函数

int stat(const char *pathname, struct stat *statbuf); //通过文件名
int fstat(int fd, struct stat *statbuf); //通过文件描述符
int lstat(const char *pathname, struct stat *statbuf); //在链接文件上处理不同

函数从pathname/fd这个文件中获取信息,存入statbuf结构体中
stat结构体内容如下:

struct stat {
	dev_t     st_dev; //包含当前设备的文件的ID
    ino_t     st_ino; //inode
    mode_t    st_mode; //权限信息rwx
    nlink_t   st_nlink; //硬链接数
    uid_t     st_uid; //userID
    gid_t     st_gid; //groupID
    dev_t     st_rdev; //设备的ID
    off_t     st_size; //大小(单位字节)
    blksize_t st_blksize; //一个blocksize有多大,一般是512B
    blkcnt_t  st_blocks; //当前这个文件占了多少个512字节的块
};

注意这里的size并不指文件的大小,只是一个属性,比如写一个10G的空洞文件,size是10G,但是占的空间只有几M。实际大小由blksize和blocks决定。

返回值

三个函数都是成功返回0,失败返回-1

文件访问权限

stat结构体中的st_mode是个16位的位图,其中有文件类型的信息、文件访问权限以及特殊权限位,文件类型有dcb-lsp这七种,有七个宏用来看传入的st_mode是什么类型的文件:

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?
S_ISSOCK(m) socket?

还有一个方法是让st_mode和另一个16位全1的位图相与,就可以得到st_mode实际是什么文件

switch (sb.st_mode & S_IFMT) {
	case S_IFBLK:  printf("block device\n");            break;
    case S_IFCHR:  printf("character device\n");        break;
    case S_IFDIR:  printf("directory\n");               break;
    case S_IFIFO:  printf("FIFO/pipe\n");               break;
    case S_IFLNK:  printf("symlink\n");                 break;
    case S_IFREG:  printf("regular file\n");            break;
    case S_IFSOCK: printf("socket\n");                  break;
    default:       printf("unknown?\n");                break;
}

umask

创建文件后的默认属性是0666 & ~umask的值

举例
0666: 000 110 110 110
~umask(0022): 111 111 101 101
0666 & ~umask:000 110 100 100
即默认属性是rw-r–r--

umask的作用是防止产生权限过松的文件

文件权限更改:chmod、fchmod

命令的使用看chmod
在编程过程中需要临时一个文件的权限,可以使用函数的chmod

int chmod(const char *pathname, mode_t mode);
int fchmod(int fd, mode_t mode);
//使用样例
chmod(filename, 0700);
chmod(fd, 0700);

粘着位(t位)

原本用于给二进制执行文件在内存中保留其使用痕迹,现在cache的出现使得用处已经逐渐不大。现在常用于给目录设置t位

文件系统:FAT、UFS

硬链接和符号链接

硬链接:用一个不同的名字关联源文件的inode,类似两个指针指向同一块内存。如果把源文件删了,另一个还能继续使用,只有链接计数归0才会真正删除文件。建立硬链接有限制:不能给分区建立,不能给目录建立
符号链接:相当于windows中的快捷方式,本身是独立的文件,拥有自己的inode,只不过文件内容是源文件的路径。如果删除源文件会导致符号链接失效。使用readlink指令可以查看符号链接指向的文件。符号链接可跨分区,可给目录建立
这里提一下之前讲过的stat函数,其中有个lstat:

int lstat(const char *pathname, struct stat *statbuf);

如果给lstat函数传入的是符号链接文件,则获取的是符号链接文件的属性。而给stat传入符号链接文件,得到的是所指向的目标文件的属性

ln指令使用link函数实现的:

int link(const char *oldpath, const char *newpath);
//创建newpath链接指向oldpath

还有个函数unlink:

int unlink(const char *pathname);

这个命令从文件系统中中删除一个名字,若这个名字是指向这个文件的最后一个链接,并且没有进程处于打开这个文件的状态,则删除这个文件,释放这个文件占用的空间,如果有进程打开这个文件,则要等到进程关闭这个文件之后才删除。如果这个名字指向一个符号链接,则删除这个符号链接。

目录的创建和销毁:mkdir、rmdir(只能删除空目录)

更改当前工作路径

cd是用chdir函数进行实现

int chdir(const char *path);
int fchdir(int fd);

传入想切换去的路径
还有个函数用来获取当前工作路径

 char *getcwd(char *buf, size_t size);

分析目录/读取目录内容

glob

用于Linux文件系统中路径名称的模式匹配,即查找文件系统中指定模式的路径。

int glob(const char *pattern, int flags,
		 int (*errfunc) (const char *epath, int eerrno),
         glob_t *pglob);

pattern是个通配符,描述一个文件路径的模式。

flag是或一些符号信息,有以下几个常用的:

  • GLOB_NOSORT
    按照pattern找出来的文件默认按照字典序排序。添加这个flag可以让他不排序
  • GLOB_NOCHECK
    如果按照pattern什么都没找到,就返回pattern本身
  • GLOB_APPEND
    将匹配到的内容追加到pglob后

第三个参数是一个函数指针,如果glob函数解析出错,将会把出错的路径和eerrno都传入这个函数。

第四个参数是一个结构体,内容如下:

typedef struct {
	size_t   gl_pathc; //匹配到的路径数,类似argc
    char   **gl_pathv; //匹配到的路径,类似argv
    size_t   gl_offs;     /* Slots to reserve in gl_pathv.  */
} glob_t;

返回值

成功返回0,否则返回:

  1. GLOB_NOSPACE
    内存不足
  2. GLOB_ABORTED
    读取出错
  3. GLOB_NOMATCH
    没找到匹配

使用样例

#define PAT     "/etc/.*"

#if 0
static int errfunc(const char *epath, int eerrno)
{
        puts(epath);
        fprintf(stderr, "ERROR MSG: %s\n", strerror(eerrno));
        return 0;
}
#endif

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

        int err = glob(PAT, GLOB_NOSORT, NULL, &globres);
        if (err)
        {
                printf("ERROR CODE: %d\n", err);
                exit(1);
        }

        for (int i = 0; i < globres.gl_pathc; i++)
                puts(globres.gl_pathv[i]);
		globfree(&globres); //别忘了释放
        exit(0);
}

使用目录相关函数

像操作文件函数一样使用目录的函数

opendir、closedir

通过目录名打开/关闭一个目录流

DIR *opendir(const char *name);
DIR *fdopendir(int fd); //open可以打开目录,也会得到一个描述符
//成功则返回目录流指针,否则返回空
int closedir(DIR *dirp);
readdir

用于读取一个目录

struct dirent *readdir(DIR *dirp);

返回一个结构体指针,存有目录的基本属性,该指针内容如下:

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 */
};
这篇关于文件和目录的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!