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));
}

参考链接

最后

  1. 觉得不错,帮忙点个推荐呗,您的支持是对我最大的激励
  2. 欢迎我的公众号:「心谭博客」,只专注于前端 + 算法的原创分享

由于个人精力有限,很多系列和历史文章没有即时同步,请前往「前端图谱」&「算法题解」,保证您有所收获。

深入Nodejs模块fs - 文件系统操作的更多相关文章

  1. nodejs模块fs——文件操作api

    // fs模块常用api // 读取文件 .写入文件 .追加文件. 拷贝文件 .删除文件 // 读取文件 // fs.readFile(path[, options], callback) // fs ...

  2. 02-Node.js学习笔记-系统模块fs文件操作

    2.1.什么是系统模块 Node 运行环境提供的API,因为这些API都是以模块化的方式进行开发的,所有我们又称Node运行环境提供的API为系统模块 3.1系统模块fs文件操作 //f :file ...

  3. nodeJS之fs文件系统

    前面的话 fs文件系统用于对系统文件及目录进行读写操作,本文将详细介绍js文件系统 概述 文件 I/O 是由简单封装的标准 POSIX 函数提供的. 通过 require('fs') 使用该模块. 所 ...

  4. nodejs模块——fs模块

    fs模块用于对系统文件及目录进行读写操作. 一.同步和异步 使用require('fs')载入fs模块,模块中所有方法都有同步和异步两种形式. 异步方法中回调函数的第一个参数总是留给异常参数(exce ...

  5. nodejs模块——fs模块 读取文件

    readFile读取文件 fs.readFile(filename,[option],callback) 方法读取文件. 参数说明: filename String 文件名 option Object ...

  6. Node.js核心模块-fs文件系统

    fs是file-system的简写,文件系统的意思.在Node中如果想要进行文件操作,就必须引入fs这个核心模块. 引入 const fs = require('fs') fs.readFile(pa ...

  7. nodejs模块——fs模块 使用fs.write读文件

    fs.write() fs.read(fd,buffer,offset,length[,position],callback(err,bytesWritten,buffer))接收6个参数. 参数说明 ...

  8. nodejs模块——fs模块 使用fs.read读文件

    使用fs.read读文件 fs.read() 先介绍fs.open. fs.open(path,flags,[mode],callback)方法用于打开文件,以便fs.read()读取. 参数说明: ...

  9. nodejs模块——fs模块 WriteFile写入文件

    WriteFile写入文件 使用fs.writeFile(filename,data,[options],callback)写入内容到文件. 参数说明: filename String 文件名 dat ...

随机推荐

  1. vue-cli3 使用 svg-sprite-loader 的坑

    chainWebpack: config => { config.module.rules.delete("svg"); //重点:删除默认配置中处理svg, //const ...

  2. koa2入门--09.art-template高速模板引擎的使用

    首先在项目文件夹下使用 cmd,输入:npm install --save art-template koa-template art-template语法参考:http://aui.github.i ...

  3. 数据库java包

    package com.hgkj.model.dao.impl; import java.sql.*; public class DBManager { private static final St ...

  4. FreeNOS学习2——操作系统是如何启动的

    The System Boot Process Explained:https://www.webopedia.com/DidYouKnow/Hardware_Software/BootProcess ...

  5. 定位、识别;目标检测,FasterRCNN

    定位: 针对分类利用softmax损失函数,针对定位利用L2损失函数(或L1.回归损失等) 人关节点检测 针对连续变量和离散变量需要采用不同种类的损失函数. 识别: 解决方案: 1.利用滑动窗口,框的 ...

  6. Linux下搭建实现HttpRunnerManager的异步执行、定时任务及任务监控

    前言 在之前搭建的HttpRunnerManager接口测试平台,我们还有一些功能没有实现,比如异步执行.定时任务.任务监控等,要完成异步执行,需要搭建 RabbitMQ 等环境,今天我们就来实现这些 ...

  7. python写冒泡排序

    冒泡就是重复地遍历要排序的数列,一次比较两个元素(泡泡),如果他们的顺序错误就把他们交换过来,像泡泡一样,依次按照顺序上升排列. 冒泡排序算法的运作如下: 比较相邻的元素.如果第一个比第二个大(升序) ...

  8. 日志管理-log4j与slf4j的使用

    一.概述 1.log4j: Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台.文件.GUI组件,甚至是套接口服务器.NT的事件记录器.UNIX Sy ...

  9. 根据设备id自动打开本设备的串口

    对于串口设备经常遇到重新拔插串口设备时候,程序又需要重新选择串口打开.对此很少麻烦的要死. 现在我们可以根据该设备的id去遍历串口设备,一旦符合就打开此串口即可. public void init() ...

  10. SpringBoot整合Thymeleaf-基于SpringBoot2.X版本

    1.为啥要用Thymeleaf模板引擎?现在不都前后端分离了么? 熊dei们,别着急,我们先来谈谈为啥开始用Thymeleaf模板引擎,先照顾照顾下我们这些可爱的小白童鞋.... 为啥开始用Thyme ...