banli17 / note

学习记录
https://banli17.github.io/note/docs/intro
MIT License
17 stars 2 forks source link

Node.js fs 模块 #111

Open banli17 opened 2 years ago

banli17 commented 2 years ago

fs 是 nodejs 核心模块,提供了文件系统的 API。

2022-02-14-20-45-59

权限位

2022-08-09-21-11-56

上图中,第一行最左边的一段字符串 drwxr-xr-x 解释如下:

d 目录
rwx 文件所有者权限
r-x 文件所属组权限
r-x 其他用户权限

@ 符号是 mac 扩展的,如果文件或目录有扩展属性,则使用 -l 选项执行 ls 命令时,会在权限许可字段后面附加一个字符 @。如果文件或目录有扩展安全信息,则使用 -l 选项执行 ls 命令时,会在权限许可字段后面附件一个字符 +。

通过 chmod -h 444 1.txt 命令,可以将文件修改为只读,然后就只能查看文件了,在修改文件时会报错。

2022-08-09-21-09-59

如果文件没有 x 权限,在执行文件时会报权限错误。

2022-08-09-21-11-31 2022-02-14-20-37-38 2022-02-14-20-50-23

windows 默认是 rw, 八进制文件权限表示为 0o666, 十进制表示为 438

文件描述符 flags

2022-08-09-21-34-49

上图中要注意的是:

文件标识符

fd 就是操作系统分配给被打开文件的标识,由于系统不同, nodejs 将 fd 抽象成了数字,从 3 开始。 0, 1, 2 分别是输入流、输出流、错误流。

为什么需要 open 和 close ?

因为 writeFile、readFile 是一次性加载到内存中的。对于大文件来说,需要一种流的方式处理文件:打开、读取、关闭。

大文件读写操作

2022-08-07-12-54-00

常用 API

获取文件信息

文件和目录操作

node v16 废弃了 fs.rmdir() 的 recursive 参数。使用 rm() 代替

stat

stat 方法用于获取文件的信息,如果文件不存在,会报错。

fs.stat(filepath, (err, stats) => {
  stats.isFile()
  stats.isDirectory()
  stats.isSymbolicLink()
  stats.size // 字节
})

软链接与硬链接

软链接 soft link -> system file -> disk real file 硬链接 hard link -> disk real file <- system file

因为循环引用的问题,所以 linux 里目录无法创建硬链接。

在 linux 里一切都是文件,目录是一种特殊的文件。下面用 js 来模拟:

class iNode {} // 代表真实的文件节点
let inode1 = new iNode()
let inode2 = new iNode()
let inode3 = new iNode()

// dir2/dir1
let file1 = {
  link: inode1,
}
let file2 = {
  link: inode2,
}
let file3 = {
  link: inode3,
}
let dir1 = {
  parent: '..',
  current: '.',
  children: [file1, file2],
}
let dir2 = {
  parent: '..',
  current: '.',
  children: [dir1, file3],
}

function hardLink(file) {
  return {
    link: file.link, // 实际也是只想了 inode
  }
}

function softLink(file) {
  return file
}

let hardLink1 = hardLink(file1)
deleteFile(file1) // 删除文件时, hardLink1 并没有删除掉, inode1 也还在

let softLink1 = softLink(file1)
deleteFile(file1) // 因为 file1.link = null 了,所以 softLink 就和 inode 也断链了

function deleteFile(file) {
  // 删除硬盘真实文件
  // 检查 inode 的链接数,进行清理 inode,有点像 gc 回收
  const num = checkLinkNum(file.link)
  if (num === 0) {
    file.inode = null
  }

  // 删除系统文件里的显示
  file.link = null
  file = null
}

fs-extra