【APUE】文件系统 — 目录和文件

news2024/11/24 20:48:48

目录

1、获取文件属性 

2、文件访问权限

3、umask

4、文件权限管理

4.1 chmod

4.2 fchmod

5、粘住位

6、文件系统举例

6.1 FAT系统

6.2 UFS系统

6.3 补充

7、链接

7.1 硬链接

7.2 符号链接

7.3 相关函数

7.3.1 link 

7.3.2 unlink 

7.3.3 remove  

7.3.4 rename

8、utime

9、目录的创建和销毁

9.1 mkdir 

9.2 rmdir 

10、工作路径相关

10.1 chdir && fchdir

10.2 getcwd 

11、分析目录

11.1 glob

11.2 opendir

11.3 closedir

11.4 readdir

11.5 rewinddir

11.6 seekdir

11.7 telldir​​​​​​​


  • 目标:代码实现类似 ls 命令的功能 

1、获取文件属性 

我们希望实现类似 ls 命令的功能,首先要对 LINUX 下的 ls 命令有一定了解

  • ls:显示当前路径下的内容
  • ls -a:连同隐藏文件一起显示
  • ls -i:连同文件的 inode 一起显示
  • ls -l:显示文件详细属性(user name 和 group name)
  • ls -n:显示文件详细属性(user id 和 group id)

获取文件属性的函数:stat (其实 stat 也被封装成了一个同名 UNIX 命令,能够显示文件属性)

man 2 stat

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

int stat(const char *pathname, struct stat *statbuf);
int fstat(int fd, struct stat *statbuf);
int lstat(const char *pathname, struct stat *statbuf); // lstat() is identical to stat(), except that if pathname is a symbolic link, then it returns information  about the link itself, not the file that it refers to.

功能:获取文件状态属性

  • pathname — 待获取属性的文件
  • fd — 表征待获取属性的文件
  • 调用成功返回 0;失败返回 -1,并将错误信息转化为某个值设置给全局变量 errno
  • statbuf —  指向一块结构体,调用函数会将有关文件的一些属性信息存入这块结构体中

有哪些信息会填入这块结构体呢?struct stat 类型的说明如下:

struct stat {
    dev_t st_dev;     /* 文件所在的设备编号 */
    ino_t st_ino;     /* 索引结点编号 */
    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; /* 文件系统的I/O块大小 */
    blkcnt_t st_blocks;  /* 块数 */
    time_t st_atime;   /* 访问(读)时间 */
    time_t st_mtime;   /* 更改文件数据时间 */
    time_t st_ctime;   /* 更改文件亚数据时间 */
}; 

通过这个结构体,可以获取很多和文件有关的信息


代码示例:打印出文件的大小 

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

// 注意返回值是off_t类型
static off_t flen(const char *fname) {    // const表示不更改文件名
    struct stat statres; // 声明一个stat类型的结构体statres
    if(stat(fname, &statres) < 0) {
        perror("stat()");
        exit(1);
    }
	// 返回st_size成员
    return statres.st_size;
}


int main(int argc, char **argv) {
    if(argc < 2) {
        fprintf(stderr, "Usage...\n");
        exit(1);
    }

    printf("total size: %lld\n", (long long)flen(argv[1]));

    exit(0);
}

off_t 类型用于指示文件的偏移量,通常就是 long 类型,其默认为一个 32 位的整数,在 gcc 编译中会被编译为 long int 类型,在 64 位的 Linux 系统中则会被编译为 long long int,这是一个 64 位的整数,其定义在 unistd.h 头文件中可以查看


注意:在描述文件属性的 stat 结构体中,有以下三个描述文件大小的成员

struct stat {
    off_t st_size;    /* 文件大小,以字节为单位*/
    blksize_t st_blksize; /*文件系统的I/O块大小*/
    blkcnt_t st_blocks;  /* 块数 */
}; 

其中,块大小一般为4096字节,即4KB(一个块为连续8个扇区,每个扇区为512B);块数为该文件的占用的块数

注意:st_size ≠ st_blksize * st_blocks;或者说,st_size 是文件的逻辑大小(可以看成文件的一个属性),而 st_blksize *  st_blocks 是文件实际的物理大小


代码示例:构建一个 st_size ≠ st_blksize * st_blocks 的文件

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main(int argc, char **argv) {
    int fd;

    if(argc < 2) {
        fprintf(stderr, "Usage...");
        exit(1);
    }

    if((fd = open(argv[1], O_WRONLY|O_CREAT|O_TRUNC, 0600)) < 0) {
        perror("open");
        exit(1);
    }
	// 先让指针从文件开头向后移动5G-1个字节
    lseek(fd, 5LL * 1024LL * 1024LL * 1024LL - 1LL, SEEK_SET);
    // 如果上述代码写成 5*1024*1024*1024-1,则编译器可能默认在做int之间的计算,那么计算结果也会被裁切为int,会整型溢出
	// 在最后写入一个空字符
    write(fd, "", 1);

    close(fd);

    exit(0);
}


通过该程序创建文件 file,再 stat file

可以看出:文件大小为5368709120B(字节),但是占用的块数却为8,即实际占用的物理大小为4KB * 8 = 32KB(注意这在 UNIX 环境下和 Windows 环境下是不一样的,Windows 系统下,文件大小就等于文件实际占用的物理大小)

这样的文件我们称之为空洞文件 

定义:从偏移文件头部 5368709120 字节处开始写入数据,也就意味着 1~5368709119 字节之间出现了一个空洞,因为这部分空间并没有写入任何数据,所以形成了空洞,这部分区域就被称为文件空洞,那么相应的该文件也被称为空洞文件文件空洞部分实际上并不会占用任何物理空间,直到在某个时刻对空洞部分进行写入数据时才会为它分配对应的物理空间,但是空洞文件形成时,逻辑上该文件的大小(即 st_size)是包含了空洞部分的大小的

拷贝文件的空洞部分时,不会发生 read/write 系统调用,而会直接 lseek 定位到空洞部分的下一位置,继续读取/写入数据 

空洞文件的作用 

空洞文件对多线程共同操作文件是很有用的,因为我们在创建一个很大文件的时候,我们就把一个文件分成很多的段,然后采用多线程的方式,让每个线程负责写入其中的某一段的数据。这样的话比我们用单个线程写入是快很多的

  • 在使用迅雷下载文件时,还未下载完成,就发现该文件已经占据了全部文件大小的空间,这也是空洞文件;下载时如果没有空洞文件,多线程下载时文件就只能从一个地方写入,这就不能发挥多线程的作用了;如果有了空洞文件,可以从不同的地址同时写入,就达到了多线程的优势
  • 在创建虚拟机时,你给虚拟机分配了 100G 的磁盘空间,但其实系统安装完成之后,开始也不过只用了 3、4G 的磁盘空间,如果一开始就把 100G 分配出去,资源是很大的浪费

2、文件访问权限

注意:在描述文件属性的 stat 结构体中,有这样一个成员

struct stat {
    mode_t st_mode;    /* 文件类型和权限*/
}; 

st_mode是一个16位的位图,用于表示文件类型,文件访问权限以及特殊权限位

它的类型为mode_t,其实就是普通的unsigned int,但是只是用了低16位

那么每一位的含义是什么?

通过查看手册 man 7 inode 可以查看详情

首先,高4位表示文件类型 

低9位表示文件的权限 

中间3位表示设置用户 ID 位(set-user-ID),设置组 ID 位(set-group-ID),sticky 位

具体什么含义呢?怎么看的呢?下面详解

man 手册中显示的值只是将位图转化为八进制表示罢了 


3、umask

umask 存在的意义:防止创建出权限过松的文件

权限公式:mode & ~umask

LINUX 默认的 umask 值:八进制数 0022 (注意第一个0只是说明这个数是八进制,是个符号) 

则:

LINUX 默认创建文件的实际权限:0666 & ~umask = 0666 & ~0022 = 0644

LINUX 默认创建文件夹的实际权限:0777 & ~umask = 0777 & ~0022 = 0755

使用 open 系统调用创建文件的实际权限:mode & ~umask

查看和更改系统的 umask 值(一个八进制数,macOS 下把八进制数开头的那个表示其为八进制数的 0 省略了)

上面介绍的 umask 是个命令。这个命令是由一个同名函数封装出来的

查看手册:man 2 umask 

#include <sys/stat.h>

mode_t umask(mode_t cmask);

The umask() routine sets the process's file mode creation mask to cmask and returns the previous value of the mask.


4、文件权限管理

4.1 chmod

先看看 chmod 命令

chmod [对谁操作(ugoa)][操作符 (+-=)][赋予的权限(rwxs或数字)] 文件名1 文件名2...
chmod [八进制mode] 文件名1 文件名2...

如果想在一个进程中临时修改某个文件的权限,可以用 chmod 函数 

#include <sys/types.h>
#include <sys/stat.h>

int chmod(const char *path, mode_t mode);
  • path — 指定文件
  • mode — 指定权限(八进制数)

注意,用 chmod 设置的时候,不用考虑 umask 

4.2 fchmod

#include <sys/types.h>
#include <sys/stat.h>

int fchmod(int fd, mode_t mode);
  • fd — 指定文件为 fd 所关联的文件
  • mode — 指定权限 

5、粘住位

如果一个可执行程序文件的这一位被设置了,那么在该程序第一次被执行并结束时,其程序正文部分的一个副本仍被保存在交换区,(程序的正文部分是机器指令部分)。这使得下次执行该程序时能较快地将其装入内存中。现今较新的 UNIX 系统大多数都配置有虚拟存储系统以及快速文件系统,所以不再需要使用这种技术。

现今的系统扩展了粘住位的使用范围,允许针对目录设置粘住位。如果对一个目录设置了粘住位,则只有对该目录具有写权限的用户在满足下列之一的情况下,才能删除或更名该目录下的文件或目录:

  • 拥有此文件
  • 拥有此目录
  • 是超级用户

6、文件系统举例

文件系统:用于文件或数据的储存和管理

6.1 FAT系统

本质:静态存储的单链表,即用数组实现的单链表

假设每个结构体中的 data 部分储存特定量的数据,那么如果有一个大文件,单个结构体中的 data 不足以存放这个大文件的所有数据,那么就需要多个结构体来存放这个大文件的数据。

显然,多个结构体之间是按照单链表逻辑进行连接的,访问大文件的数据需要涉及到遍历单链表,故 FAT 系统储存大文件性能不好

注意这只是个超级超级超级简化版本的示意图,了解即可 

6.2 UFS系统

UFS 系统的几个组成部分了解一下即可

inode 和数据块示意图如下

上图建议从左上角逆时针看。。。 

还有 i 位图和块位图

UFS 和 FAT 不同,UFS 不善于管理小文件 

如果是一个小文件,UFS 为文件分配一个 inode 结构体,结构体里的数据块指针数组里面至少会包含一个块指针指向 4KB 大小的块,可是要是这个文件不足 4KB,就会造成数据块空间的浪费

因此,如果小文件很多,是有可能出现 inode 结构体数组满了,而块还没满的情况。查找结构体中的数据需要遍历很多结构体,比较慢。


6.3 补充

刚刚说的几乎所有和文件有关的信息都在inode结构体中,但不包含文件名

文件的文件名统一存放在目录文件

某个目录的目录文件存在于该目录下,目录文件的目录项记录了目录中文件的 inode 及其对应的文件名

当用 vim 打开一个目录时,其实就查看到了目录文件的一部分内容


7、链接

7.1 硬链接

创建硬链接的命令

ln src dest # 为src创建名为dest的硬链接

命令示例

如图,stat 查看文件 testFile 的信息,发现链接数为 1,经过创建硬链接后,硬链接和源文件的链接数都变成了 2,但是硬链接和源文件的 inode 号是一样的

因此,硬链接实际上是在当前目录下的目录文件多写了一行,有另外一个名字关联到了和源文件相同的 inode(相当于两个指针指向了同一空间)

即使删除源文件,硬链接文件也能正常用。硬链接本质上就是一个普通的文件,对应着一条目录项


7.2 符号链接

创建符号链接的命令

ln -s src dest # 为src创建名为dest的符号链接

特别像 Windows 下的快捷方式! 

命令示例

如图,用 stat 查看符号链接和源文件的信息,关注几个点:

  • 符号链接的 inode 与源文件的 inode 不一样
  • 符号链接的硬链接数与源文件的硬链接数都是 1
  • 源文件的 size 更大,而符号链接的 size 刚好就是源文件名的字节长度
  • 符号链接占用磁盘块为 0(UNIX将符号链接文件的属性内容放在了 inode 结构体中,就不占块了)

删除源文件后,符号链接就无法使用了

文件A与文件B的号码虽然不一样,但是文件A的内容是文件B的路径,A就是B的符号链接文件。读取文件A时,系统会自动访问导向文件B的文件名,然后再根据B的inode去访问存储在块中的数据。

而这意味着,文件A依赖于文件B而存在,若删除了文件B,打开文件A就会报错。这就是符号链接与硬链接最大的不同:文件A指向文件B的文件名,而不是inode号码,文件B的inode链接数不会发生变化


硬链接与目录项是同义词,且建立硬连接有限制:不能给分区建立,不能给目录建立

符号链接优点:可跨分区,可以给目录建立 


7.3 相关函数

根据过往经验,UNIX 中的命令很多都是由函数封装得到的,刚刚我们用的 ln 命令自然也不例外

后续介绍函数时,需要脑海中想想这些函数调用后,对目录文件进行了怎样的更改

7.3.1 link 

man 2 link

#include <unistd.h>

int link(const char *oldpath, const char *newpath);

功能:为已存在的文件创建一个硬链接

  • oldpath — 源文件
  • newpath — 硬链接文件名

当创建硬链接后,可以说硬链接和源文件的地位是平等的 


7.3.2 unlink 

man 2 unlink

#include <unistd.h>

int unlink(const char *pathname);

功能:从文件系统删除一个文件名

        unlink()  deletes  a name from the filesystem.  

        If that name was the last link to a file and no processes have the file open, the file is deleted and the space it was using is made available for reuse.

        If the name was the last link to a file but any processes still have the file open, the file  will  remain  in existence until the last file descriptor referring to it is closed.

        If the name referred to a symbolic link, the link is removed.

        If  the  name  referred  to a socket, FIFO, or device, the name for it is removed but processes which have the object open may continue to use it.

通过上述描述,有这么一个创建匿名文件的方式:

  1. 先调用 open 打开一个文件,获取一个文件描述符
  2. 立马执行 unlink,从文件系统删除该文件名

此时,该文件所占数据空间其实没有直接被释放,因为还有个打开的文件描述符表征该文件。直到调用 close 关闭该描述符时,数据空间才被真正释放


7.3.3 remove  

 man 3 remove

#include <stdio.h>

int remove(const char *pathname);

本质上是对 unlink 等函数进行了封装,这个函数是命令 rm 的实现

remove() deletes a name from the filesystem.  It calls unlink(2) for files, and rmdir(2) for directories.


7.3.4 rename

man 2 rename

#include <stdio.h>

int rename(const char *oldpath, const char *newpath);

功能:改变文件的名称或者位置 

该函数是命令 mv 的实现 


8、utime

#include <utime.h>

int utime(const char *path, const struct utimbuf *times);

功能:用于更改文件的最后访问时间和最后修改时间 

UNIX 下的三个时间属性:

  • mtime(modify time):最后一次修改文件数据内容或目录内容的时间
  • ctime(change time) :最后一次改变文件或目录亚数据(即:属性)的时间
  • atime(access time):最后一次访问文件或目录的时间

9、目录的创建和销毁

9.1 mkdir 

man 2 mkdir

#include <sys/stat.h>

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

注意:创建出目录的实际权限同时受 mode 与 umask 约束

9.2 rmdir 

man 2 rmdir

#include <unistd.h>

int rmdir(const char *path);

注意:只能删除空目录


10、工作路径相关

10.1 chdir && fchdir

man 2 chdir 

#include <unistd.h>

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

功能:修改当前进程的工作路径 

  • path — 指定切换到某个路径 
  • fd — 表征一个已经被成功打开的路径
  • 该函数是命令 cd 的实现,即该函数封装出了命令 cd

10.2 getcwd 

man 2 getcwd

#include <unistd.h>

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

功能:获取当前工作路径

  • buf — 指向一片空间,用于储存当前进程工作的绝对路径
  • size — buf 所指空间的长度
  • 返回值也是 buf
  • 该函数封装出了命令 pwd

11、分析目录

11.1 glob

man 3 glob

#include <glob.h>

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

void globfree(glob_t *pglob); // 释放pglob的成员所指向的堆内存

功能:解析模式/通配符(所谓解析,就是将字符串解析成名字

  • pattern — 通配符,要解析的 pattern,如 "/*" 表示解析出根文件下的所有文件名(不包括隐藏文件)
  • flags — flags 参数可以设置解析的特殊要求,如无特殊要求置为 0
  • errfunc — 函数指针,glob 函数执行出错会执行的函数,出错的路径会回填到 epath 中,出错的原因回填到 eerrno 中。如不关注错误可设置为NULL
  • pglob — 解析出来的结果放在这个参数里,是一个结构体指针
  • 返回值 — 成功返回 0,错误返回非 0

其中,glob_t 结构体内容如下:

typedef struct {
    // pathc与pathv类似于main函数参数argc与argv
    size_t    gl_pathc;    //匹配到的数量
    char    **gl_pathv;    //匹配到的元素放在这里
    size_t    gl_offs; 
} glob_t;

代码示例:解析路径

使用如下:


UNIX 还提供了一组对目录操作的函数,能够操作目录,和对文件操作的函数基于 FILE 结构体类似,对目录的操作基于名为 DIR 的结构体

11.2 opendir

man 3 oprndir 

#include <sys/types.h>
#include <dirent.h>

DIR *opendir(const char *name);
DIR *fdopendir(int fd);

功能:获取目录流

  • name — 获取 name 所表征目录的目录流
  • fd —  获取已经打开的 fd 所表征目录的目录流
  • 成功返回指向目录流 DIR 的指针;失败返回 NULL 并设置 errno

11.3 closedir

man 3 closedir

#include <sys/types.h>

#include <dirent.h>

int closedir(DIR *dirp);

功能:关闭目录流 

opendir 的逆操作,通过 opendir 获取的目录流应该通过 closedir 关闭 

11.4 readdir

man 3 readdir

#include <dirent.h>

struct dirent *readdir(DIR *dirp);

功能:从目录流读取下一条目录项

The  readdir()  function returns a pointer to a dirent structure representing the next directory entry in the directory stream pointed to by dirp.  It returns NULL on reaching the end of the directory  stream  or  if  an error occurred. 

读取到的目录项内容填充到一个结构体,并返回指向其的指针

返回的结构体指针代表了读取到的目录项,结构体内容如下:

struct dirent {
    ino_t          d_ino;       /* Inode number */
    off_t          d_off;       /* 现代操作系统中不对其内容做任何假设 */
    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 */
};

11.5 rewinddir

 man 3 rewinddir

#include <sys/types.h>

#include <dirent.h>

void rewinddir(DIR *dirp);

功能:重置目录流

The rewinddir() function resets the position of the directory stream dirp to the beginning of the directory. 

调用该函数后,接下来若再通过 readdir 读取目录流将重新从第一条目录项开始读取 

11.6 seekdir

man 3 seekdir 

#include <dirent.h>

void seekdir(DIR *dirp, long loc);

功能:设置下一次 readdir 从目录流中读取目录项的起始位置

11.7 telldir

man 3 telldir

#include <dirent.h>

long telldir(DIR *dirp);

功能:返回 readdir 当前读取到目录流的哪个位置


国庆快乐!🎉🎉

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1057038.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JavaWeb项目:smbms(mysql)

1.准备工作&#xff0c;创建数据库 CREATE DATABASE smbms;USE smbms;CREATE TABLE smbms_address (id BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT 主键ID,contact VARCHAR(15) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT 联系人姓名,addressDesc VARCHAR(50) COLLATE u…

字符串,字符数组,类型转换,整数越界,浮点数,枚举

目录 自动类型转换 强制类型转换 数据类型 sizeof 数据类型所占字节数 整数越界 浮点数 字符型 字符串变量 ​编辑字符串的输入输出 main函数的参数 &#xff0c;argc,argv 单个字符输入输出 putchar getchar strlen,strcmp,strcat,strchr,strstr strlen 求字…

数学建模Matlab之检验与相关性分析

只要做C题基本上都会用到相关性分析、一般性检验等&#xff01; 回归模型性能检验 下面讲一下回归模型的性能评估指标&#xff0c;用来衡量模型预测的准确性。下面是每个指标的简单解释以及它们的应用情境&#xff1a; 1. MAPE (平均绝对百分比误差) 描述: 衡量模型预测的相对…

在visual studio里配置Qt插件并运行Qt工程

Qt插件&#xff0c;也叫qt-vsaddin&#xff0c;它以*.vsix后缀名结尾。从visual studio 2010版本开始&#xff0c;VS支持Qt框架的开发&#xff0c;Qt以插件方式集成到VS里。这里在visual studio 2019里配置Qt 5.14.2插件&#xff0c;并配置Qt环境。 1 下载VS2019 下载VS2019,官…

Grander因果检验(格兰杰)原理+操作+解释

笔记来源&#xff1a; 1.【传送门】 2.【传送门】 前沿原理介绍 Grander因果检验是一种分析时间序列数据因果关系的方法。 基本思想在于&#xff0c;在控制Y的滞后项 (过去值) 的情况下&#xff0c;如果X的滞后项仍然有助于解释Y的当期值的变动&#xff0c;则认为 X对 Y产生…

nodejs+vue流浪猫狗救助领养elementui

第三章 系统分析 10 3.1需求分析 10 3.2可行性分析 10 3.2.1技术可行性&#xff1a;技术背景 10 3.2.2经济可行性 11 3.2.3操作可行性&#xff1a; 11 3.3性能分析 11 3.4系统操作流程 12 3.4.1管理员登录流程 12 3.4.2信息添加流程 12 3.4.3信息删除流程 13 第四章 系统设计与…

nodejs+vue交通违章查询及缴费elementui

第三章 系统分析 10 3.1需求分析 10 3.2可行性分析 10 3.2.1技术可行性&#xff1a;技术背景 10 3.2.2经济可行性 11 3.2.3操作可行性&#xff1a; 11 3.3性能分析 11 3.4系统操作流程 12 3.4.1管理员登录流程 12 3.4.2信息添加流程 12 3.4.3信息删除流程 13 第四章 系统设计与…

一文拿捏分布式、分布式缓存及其问题解决

1.分布式 1.集中式 传统的计算模型通常是集中式的&#xff0c;所有的计算任务和数据处理都由单一的计算机或服务器完成。然而&#xff0c;随着数据量和计算需求的增加&#xff0c;集中式系统可能会面临性能瓶颈和可靠性问题。 故而引出了分布式↓↓↓↓↓↓↓↓↓↓↓↓↓↓…

一文拿捏基于redis的分布式锁、lua、分布式性能提升

1.分布式锁 jdk的锁&#xff1a; 1、显示锁&#xff1a;Lock 2、隐式锁&#xff1a;synchronized 使用jdk锁保证线程的安全性要求&#xff1a;要求多个线程必须运行在同一个jvm中 但现在的系统基本都是分布式部署的&#xff0c;一个应用会被部署到多台服务器上&#xff0c;s…

40 二叉树的直径

二叉树的直径 总结&#xff1a;两个节点之间最长路径 路径的结点数 - 1题解1 递归——DFS 给你一棵二叉树的根节点&#xff0c;返回该树的 直径。 二叉树的直径是指树中任意两个节点之间最长路径的长度。这条路径可能经过也可能不经过根节点 root 。 两节点之间路径的长度由…

Python无废话-基础知识字典Dictionary详讲

“字典Dictionary” 是一种无序、可变且可嵌套的数据类型&#xff0c;用于存储键值对。字典使用花括号{}来定义&#xff0c;并用逗号分隔键值对。本文对字典常使用方法&#xff0c;创建字典、添加字典、删除字典、如何获取字典做了知识归纳。 字典有以下几个特征&#xff1a; …

92、Redis ------- 使用 Lettuce 操作 Redis 的方法和步骤----(文字讲解无代码)

lettuce &#xff1a;英语的意思&#xff1a;生菜 是一个用来操作redis的框架&#xff0c;springboot内置默认支持的也是 lettuce &#xff0c;也可以自己改成 jedis Jedis 也是一个用来操作redis的框架 ★ Lettuce的核心API RedisURI&#xff1a;用于封装Redis服务器的URI信息…

家用无线路由器如何用网线桥接解决有些房间无线信号覆盖不好的问题(低成本)

环境 光猫ZXHN F6600U 水星MW325R 无线百兆路由器 100M宽带&#xff0c;2.4G无线网络 苹果手机 安卓平板电脑 三室一厅94平 问题描述 家用无线路由器如何用网线桥接解决有些房间无线信号不好问题低成本解决&#xff0c;无线覆盖和漫游 主路由器用的运营商的光猫自带无…

cf 解题报告 01

E. Power of Points Problem - 1857E - Codeforces 题意&#xff1a; 给你 n n n 个点&#xff0c;其整数坐标为 x 1 , … x n x_1,\dots x_n x1​,…xn​&#xff0c;它们位于一条数线上。 对于某个整数 s s s&#xff0c;我们构建线段[ s , x 1 s,x_1 s,x1​], [ s , x…

【Java】super 关键字用法

目录 this与super区别 1.访问成员变量-示例代码 继承中构造方法的访问特点 2.访问构造方法-示例代码&#xff1a; 继承中成员方法访问特点 3.访问成员方法-示例代码&#xff1a; super 关键字的用法和 this 关键字相似 this : 代表本类对象的引用super : 代表父类存储空间…

VBA技术资料MF64:遍历单元格搜索字符并高亮显示

【分享成果&#xff0c;随喜正能量】不要在乎他人的评论&#xff0c;不必理论与他人有关的是非&#xff0c;你只要做好自己就够了。苔花如米小&#xff0c;也学牡丹开。无论什么时候&#xff0c;都要有忠于自己的勇气&#xff0c;去做喜欢的事&#xff0c;去认识喜欢的人&#…

JUC中的设计模式

文章目录 1. 终止模式之两阶段终止模式 1. 终止模式之两阶段终止模式 需求&#xff1a;用一个线程每两秒检测***状态&#xff0c;当不想检测时&#xff0c;用另一个线程将其停止 在一个线程 T1 中如何“优雅”终止线程 T2&#xff1f;这里的【优雅】指的是给 T2 一个料理后事…

JVM相关概念

JVM&#xff0c;全程Java Virtual Machine&#xff0c;是java虚拟机的意思&#xff01; 是一个类似计算机的存在&#xff0c;是在计算机上模拟真实计算机运行的平台&#xff0c;它代替Java代码和各种计算机设备之间的交互&#xff01; Java程序把代码翻译成字节码交给虚拟机&a…

借助Log360实现综合可见性的增强网络安全

当今的企业对技术的依赖程度前所未有&#xff0c;因此强大的威胁检测和响应策略变得至关重要。在现代世界中&#xff0c;网络犯罪分子不断寻找新的、富有创意的方式&#xff0c;以侵入组织的网络并窃取敏感数据。综合性的可见性是一个关键要素&#xff0c;有时被忽视&#xff0…

23-properties文件和xml文件以及dom4j的基本使用操作

特殊文件 我们利用这些特殊文件来存放我们 java 中的数据信息&#xff0c;当数据量比较大的时候&#xff0c;我们可以利用这个文件对数据进行快速的赋值 对于多个用户数据的存储的时候我们要用这个XML来进行存储 关于这些特殊文件&#xff0c;我们主要学什么 了解他们的特点&…