专栏首页YuanXinNodeJS模块研究 - fs

NodeJS模块研究 - fs

node 的fs文档密密麻麻的 api 非常多,毕竟全面支持对文件系统的操作。文档组织的很好,操作基本分为文件操作、目录操作、文件信息、流这个大方面,编程方式也支持同步、异步和 Promise。

本文记录了几个文档中没详细描写的问题,可以更好地串联fs文档思路:

  • 文件描述符
  • 同步、异步与 Promise
  • 目录与目录项
  • 文件信息
  • stream

文件描述符

文件描述符是一个非负整数。它是一个索引值,操作系统可以根据它来找到对应的文件。

在 fs 的很多底层 api 中,需要用到文件描述符。在文档中,描述符通常用fd来代表。例如:fs.read(fd, buffer, offset, length, position, callback)。与这个 api 相对应的是:fs.readFile(path[, options], callback)

因为操作系统对文件描述符的数量有限制,因此在结束文件操作后,别忘记 close:

const fs = require("fs");

fs.open("./db.json", "r", (err, fd) => {
    if (err) throw err;
    // 文件操作...
    // 完成操作后,关闭文件
    fs.close(fd, err => {
        if (err) throw err;
    });
});

同步、异步与 Promise

所有文件系统的 api 都有同步和异步两种形式。

同步写法

不推荐使用同步 api,会阻塞线程

try {
    const buf = fs.readFileSync("./package.json");
    console.log(buf.toString("utf8"));
} catch (error) {
    console.log(error.message);
}

异步写法

异步写法写起来容易进入回调地狱。

fs.readFile("./package.json", (err, data) => {
    if (err) throw err;
    console.log(data.toString("utf8"));
});

(推荐)Promise 写法

在 node v12 之前,需要自己借助 promise 封装:

function readFilePromise(path, encoding = "utf8") {
    const promise = new Promise((resolve, reject) => {
        fs.readFile(path, (err, data) => {
            if (err) return reject(err);
            return resolve(data.toString(encoding));
        });
    });
    return promise;
}

readFilePromise("./package.json").then(res => console.log(res));

在 node v12 中,引入了 fs Promise api。它们返回 Promise 对象而不是使用回调。 API 可通过 require('fs').promises 访问。如此一来,开发成本更低了。

const fsPromises = require("fs").promises;

fsPromises
    .readFile("./package.json", {
        encoding: "utf8",
        flag: "r"
    })
    .then(console.log)
    .catch(console.error);

目录与目录项

fs.Dir 类:封装了和文件目录相关的操作

fs.Dirent 类:封装了目录项的相关操作。例如判断设备类型(字符、块、FIFO 等)。

它们之间的关系,通过代码展示:

const fsPromises = require("fs").promises;

async function main() {
    const dir = await fsPromises.opendir(".");
    let dirent = null;
    while ((dirent = await dir.read()) !== null) {
        console.log(dirent.name);
    }
}

main();

文件信息

fs.Stats 类:封装了文件信息相关的操作。它在fs.stat()的回调函数中返回。

fs.stat("./package.json", (err, stats) => {
    if (err) throw err;
    console.log(stats);
});

注意,关于检查文件是否存在:

  • 不建议在调用 fs.open()、 fs.readFile() 或 fs.writeFile() 之前使用 fs.stat() 检查文件是否存在。而是应该直接打开、读取或写入文件,如果文件不可用则处理引发的错误
  • 要检查文件是否存在但随后并不对其进行操作,则建议使用 fs.access()。

ReadStream 与 WriteStream

在 nodejs 中,stream 是个非常重要的库。很多库的 api 都是基于 stream 来封装的。例如下面要说的 fs 中的 ReadStream 和 WriteStream。

fs 本身提供了 readFile 和 writeFile,它们好用的代价就是性能有问题,会将内容一次全部载入内存。但是对于几 GB 的大文件,显然会有问题。

那么针对大文件的解决方案自然是:一点点读出来。这就需要用到 stream 了。以 readStream 为例,代码如下:

const rs = fs.createReadStream("./package.json");
let content = "";

rs.on("open", () => {
    console.log("start to read");
});

rs.on("data", chunk => {
    content += chunk.toString("utf8");
});

rs.on("close", () => {
    console.log("finish read, content is:\n", content);
});

借助 stream 的 pipe,一行快速封装一个大文件的拷贝函数:

function copyBigFile(src, target) {
    fs.createReadStream(src).pipe(fs.createWriteStream(target));
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • NodeJS是如何监听文件的变化?

    Keywords: 操作系统差异、识别用户/编辑器操作、连续触发的优化、工程级 API。

    心谭博客
  • 设计模式 - 备忘录模式 - JavaScript

    备忘录模式:属于行为模式,保存某个状态,并且在需要的时候直接获取,而不是重复计算。

    心谭博客
  • 手写Promise的相关方法

    Promise 作为 JS 社区的异步解决方案,为开发者提供了.then()、Promise.resolve()、Promise.reject()等基本方法。除...

    心谭博客
  • NodeJs-fs模块

    今天一番在家做了一些家务,还出门逛了一圈,街上也不是完全没有人,超市、药店、菜市场人是最多的。现在才有时间来学习和写文章。

    efonfighting
  • Nodejs中读取文件目录中的所有文件

    关于Nodejs中的文件系统即File System可以参考官方Node.js v12.18.1的文档File system

    ccf19881030
  • 委内瑞拉大力发展区块链虚拟资产币种交易系统开发

    委内瑞拉国家通讯社报道,委内瑞拉总统尼古拉斯·马杜罗宣布组建一个“青年银行(Youth Bank)”,以支持他们最近刚刚推出的国家加密虚拟资产虚拟资产。此外,马...

    ruiec1212
  • ezXSS:一款功能强大的XSS盲测工具

    今天给大家介绍的是一款名叫ezXSS的漏洞测试工具,该工具可以轻松地帮助渗透测试人员完成Blind XSS漏洞的扫描任务。

    FB客服
  • 浅谈Slick(3)- Slick201:从fp角度了解Slick

      我在上期讨论里已经成功的创建了一个简单的Slick项目,然后又尝试使用了一些最基本的功能。Slick是一个FRM(Functional Relational...

    用户1150956
  • JavaScript:常用总结

    宋先生
  • dbvar:染色体结构变异数据库

    染色体结构变异structural variation(SV), 被定义为1kb以上范围的DNA结构变化,通常包括缺失,重复,倒位,易位,当然也包含拷贝数变异(...

    生信修炼手册

扫码关注云+社区

领取腾讯云代金券