第七十一期:Node的I/O操作(元数据的获取和修改)

131 阅读4分钟

这里记录工作中遇到的技术点,以及自己对生活的一些思考,周三或周五发布。

封面图

Node中的I/O操作

从某种意义上讲,Node其实是在C++的基础上又包了一层。和其他语言一样,Node和操作系统的交互也是通过I/O。

Node的I/O操作包括哪些内容

Node的I/O操作具体包括哪些内容呢?有这么几个:

  • 标准I/O
  • 文件处理 fs
  • 元数据处理 metadata
  • 文件和目录的监听
  • sockets通信

获取元数据

上节文章大致讲了Node中的标准I/O和文件操作,这篇接着讲元数据处理。

首先我们要理解一个概念,元数据指的是什么?

这里要提到的一个问题是,读取文件列表,获取权限,以及获取文件创建以及修改时间,这些是文件系统非常重要的功能,元信息指的就是这些信息。

我们可以使用tableaux这个模块将这些信息显示到终端上。

我们先安装tableaux模块。

npm install --save tableaux

然后在index.js中,写下面的内容:

const fs = require('fs')
const path = require('path')
const tableaux = require('tableaux')

const write = tableaux(
  { name: 'Name', size: 20 },
  { name: 'Created', size: 30 },
  { name: 'DevicedId', size: 30 },
  { name: 'Mode', size: 8 },
  { name: 'Lnks', size: 4 },
  { name: 'Size', size: 6 }
)

function toMeta({ file, dir }) {
  const stats = fs.statSync(path.join(dir, file))
  var { birthtime, ino, mode, nlike, size } = stats
  mode = mode.toString(9)
  size += 'B'
  return {
    file,
    dir,
    info: [birthtime, ino, mode, nlike, size],
    isDir: stats.isDirectory(),
  }
}

function output({ file, dir, info, isDir }) {
  write(file, ...info)
  if (!isDir) {
    return
  }
  const p = path.join(dir, file)
  write.arrow()
  fs.readdirSync(p).forEach((f) => {
    const stats = fs.statSync(path.join(p, f))
    const style = stats.isDirectory() ? 'blod' : 'dim'
    write[style](f)
  })
  write.newLine()
}

function print(dir) {
  fs.readdirSync(dir)
    .map((file) => ({ file, dir }))
    .map(toMeta)
    .forEach(output)
  write.newLine()
}

print(process.argv[2] || '.')

执行这个文件,我们最终可以看到下面的内容:

大体流程是print方法先用fs.readdir读取文件夹进行遍历,然后toMeta方法用fs.statSync对文件进行统计,然后返回元信息,最后output方法将信息通过write写到终端上,大体是这么一个过程。

需要注意的是

我们的代码里最后一行:

process.argv[2] || '.'

argv是process的一个命令行的参数,它是一个数组,arprocess.argv[0]可以理解为node , provess.argv[1]则是index.js , process.argv[2]不存在时默认为一个点,表示当前文件夹。

获取符号链接信息

有些人可能不理解符号链接信息是什么?

举个例子,我们都用过windows系统,都创建过桌面快捷方式,那么这个快捷方式是什么呢?

其实他就是个链接,只不过这个链接指向一个程序的启动命令,比如说我们双击浏览器图标,浏览器就打开了,其实图标也是指向了浏览器的启动文件。

我们修改index.js


const fs = require('fs')
const path = require('path')
const tableaux = require('tableaux')

const write = tableaux(
  { name: 'Name', size: 20 },
  { name: 'Created', size: 30 },
  { name: 'DevicedId', size: 30 },
  { name: 'Mode', size: 8 },
  { name: 'Lnks', size: 4 },
  { name: 'Size', size: 6 }
)

function toMeta({ file, dir }) {
  const stats = fs.statSync(path.join(dir, file))
  var { birthtime, ino, mode, nlike, size } = stats
  mode = mode.toString(9)
  size += 'B'
  return {
    file,
    dir,
    info: [birthtime, ino, mode, nlike, size],
    isDir: stats.isDirectory(),
    isSymLink: stats.isSymbolicLink(),
  }
}

function output({ file, dir, info, isDir, isSymLink }) {
  if (isSymLink) {
    outputSymLink(file, dir, info)
    return
  }
  write(file, ...info)
  if (!isDir) {
    return
  }
  const p = path.join(dir, file)
  write.arrow()
  fs.readdirSync(p).forEach((f) => {
    const stats = fs.lstatSync(path.join(p, f))
    const style = stats.isDirectory() ? 'blod' : 'dim'
    if(stats.isSymbolicLink()){
      f = '\u001b[3m'+f+'\u001b[0m'
    }
    write[style](f)
  })
  write.newLine()
}

function outputSymLink(file, dir, info) {
  write('\u001b[33]' + file + '\u001b0m', ...info)
  process.stdout.write('\ub001b[33m')
  write.arrow(4)
  write.bold(fs.readlinkSync(path.join(dir, file)))
  process.stdout.write('\u001b[0m')
  write.newline()
}

function print(dir) {
  fs.readdirSync(dir)
    .map((file) => ({ file, dir }))
    .map(toMeta)
    .forEach(output)
  write.newLine()
}

print(process.argv[2] || '.')

在toMeta方法中增加链接信息,同时增加function outputSymLink方法,然后重新执行index.js。

然后会看到,输出的内容中多了一条链接信息,my-link。

当然,前提是你需要先设置这个链接。

元信息的修改

元信息的修改主要涉及,权限,创建时间,更新时间等信息,这些都有对应的API,这里就不多说了。

下节主要说一说监听文件的变化。

最后

  • 公众号《JavaScript高级程序设计》
  • 公众号内回复”vue-router“ 或 ”router“即可收到 VueRouter源码分析的文档。
  • 回复”vuex“ 或 ”Vuex“即可收到 Vuex 源码分析的文档。

全文完,如果喜欢。

请点赞和"在看"吧,最好也加个"关注",或者分享到朋友圈。