node.js之fs模块

403 阅读8分钟

前言

fs模块是node.js的一个内置模块,可以用来对文件的读写。在js中,是不能直接读写文件的,有了Node.js之后,我们就可以实现文件的自动化处理了。

fs模块

文件 I/O 是对标准 POSIX 函数的简单封装。 通过 require('fs') 使用该模块。 所有的方法都有异步和同步的形式。

fs模块主要包括对文件内容的读取,写入,复制,删除,移动,以及文件夹的操作等。

其中异步方法的最后一个参数都是一个回调函数。 传给回调函数的参数取决于具体方法,但回调函数的第一个参数都会保留给异常。 如果操作成功完成,则第一个参数会是 null 或 undefined

当使用同步方法时,任何异常都会被立即抛出。 可以使用 try/catch 来处理异常,或让异常向上冒泡。

下面介绍fs模块的常用方法

1. 文件的读取

文件的读取分为文本读取和流式读取,它们的方法是不一样的,但是方法名里面都有一个read。其中文本读取又分为同步读取和异步读取,方法名中含有Sync的表示同步。

1.1 文本读取

文本读取分为同步读取和异步读取。

同步读取readFileSync

语法

fs.readFileSync(path[, options])
  • path: string | Buffer | URL| integer 。文件名或文件描述符。文件路径,可以是绝对路径,也可以是相对路径
  • options: object | string 。选项配置,包括编码方式

示例

const fs = require('fs');
const data = fs.readFileSync('./test.txt', 'utf-8');
console.log('data', data);

效果如下:

1680961773497(1).png

异步读取readFile

异步读取相比同步读取,多了一个回调函数的操作。同步函数如果读取出错了,函数就不继续往下走了,但是在异步函数中,如果出错了我们可以在回调函数中拿到错误信息。 语法

fs.readFile(## path[, options], callback)
  • path: string | Buffer | URL| integer 。文件名或文件描述符。文件路径,可以是绝对路径,也可以是相对路径
  • options: object | string 。选项配置,包括编码方式
  • callback: 回调函数

示例

const fs = require('fs');
const data = fs.readFile('./test.txt', 'utf-8', (err, data) => {
  console.log('err', err);
  console.log('data', data);
});

效果如下:

1680962165387.png

1.2 流式读取

一般文件的读取方式都是直接将文件读取出来, 如果文件太大了则会导致运行速度过慢,会严重影响程序的性能 流式文件读取适合较大的文件读取,可以分多次将多个内容获取。

语法

fs.createReadStream(path[,options])
  • path: string | Buffer | URL 。文件名或文件描述符。文件路径,可以是绝对路径,也可以是相对路径
  • options: object | string 。选项配置,包括编码方式, 流的开始,结束等。

示例

const fs = require('fs');

// 创建读取流对象
const rs = fs.createReadStream('./test.txt');

// 绑定data事件, 可以获取每个chunk的信息, 默认每次取出64k数据之后执行一次data回调
rs.on('data', chunk => {
  console.log('chunk', chunk);
  console.log('len', chunk.length);
})

// 读取完,执行end回调
rs.on('end', () => {
  console.log('读取完成');
})

效果如下:

image.png

1.3 文件读取的应用场景

关于文件读取,为了性能考虑,只要文件内容不是很小,我们一般都采用异步读取的方式,如果文件过大的话就采用流式读取的方式。具体使用使用场景有以下几种

  • 查看聊天记录
  • 查看日志
  • 编辑器打开文件
  • 程序运行时也是读取文件

我们需要注意的一点就是同步读取是执行同步函数,直接返回文件内容,而异步读取是在回调函数中返回内容,流式读取是需要绑定data事件才能拿到chunk,这个chunk需要转化成文件内容。

2. 文件的写入

文件的写入是和文件读取相反的功能,但是它们的使用方法差不多。

2.1 写入

写入文件也分为同步写入和异步写入。

同步写入

语法

fs.writeFileSync(file, data[,options])
  • file: string | Buffer | URL| integer 。文件名或文件描述符。文件路径,可以是绝对路径,也可以是相对路径
  • data: string | Buffer | Unit8Array
  • options: object | string 。选项配置,包括编码方式

示例

try {
  fs.writeFileSync('./test.txt', '一只快乐的小青蛙,滴滴哒哒滴滴哒');
} catch(e) {
  console.log('err', e);
}

效果如下: 原来的内容会被新写入的内容覆盖

1681008574003(1).png

需要注意的是:同步写入文件想要捕获错误需要通过try catch来捕获。

异步写入

语法

fs.writeFile(file, data[,options], callback)
  • file: string | Buffer | URL| integer 。文件名或文件描述符。文件路径,可以是绝对路径,也可以是相对路径
  • data: string | Buffer | Unit8Array
  • options: object | string 。选项配置,包括编码方式
  • callback: 回调函数

示例

fs.writeFile('./test.txt', '我是另一只快乐的小青蛙,滴滴哒哒滴滴哒', (err, data) => {
  console.log('err', err);
  console.log('data', data);
})

效果如下:

image.png

image.png

2.2 追加写入

上面的文件写入的方式是会覆盖原有的内容,现在介绍一种追加写入的方式,这种方式是在原有文件后面添加内容。追加写入也分为同步和异步

同步追加

语法

fs.appendFileSync(file, data[, options])
  • file: string | Buffer | URL| integer 。文件名或文件描述符。文件路径,可以是绝对路径,也可以是相对路径
  • data: string | Buffer | Unit8Array
  • options: object | string 。选项配置,包括编码方式

示例

fs.appendFileSync('./test.txt', '\n另一只小青蛙来了,一只青蛙一张嘴,两只眼睛四条腿');

效果如下:

image.png

异步追加

语法

fs.appendFile(file, data[, options],callback)
  • file: string | Buffer | URL| integer 。文件名或文件描述符。文件路径,可以是绝对路径,也可以是相对路径
  • data: string | Buffer | Unit8Array
  • options: object | string 。选项配置,包括编码方式
  • callback: 回调函数

示例

fs.appendFile('./test.txt', '\n两只青蛙两张嘴,四只眼睛八条腿', (err, data) => {
  console.log('err', err);
  console.log('data', data);
})

效果如下:

image.png

image.png

2.3 流式写入

针对大内存的内容写入,可以采用流式写入的方式。

语法

fs.createWriteStream(path[, options])
  • path: string | Buffer | URL 。文件名或文件描述符。文件路径,可以是绝对路径,也可以是相对路径
  • options: object | string 。选项配置,包括编码方式, 流的开始,结束等。

示例

// 创建写入流对象
let ws = fs.createWriteStream('./test.txt');

// 写入数据到流
ws.write('这是第一段很大的内容');
ws.write('\n这是第二段很大的内容');
ws.write('\n这是第三段很大的内容');

// 写入完成,关闭流
ws.end();

效果如下:

image.png

2.4 文件写入的应用场景

文件写入和读取一样,为了性能考虑,只要文件内容不是很小,我们一般都采用异步写入的方式,如果文件过大的话就采用流式写入的方式。具体使用使用场景有以下几种

  • 下载文件
  • 保存日志
  • 编辑器保存文件
  • 程序安装时也是写入文件

3. 查看资源状态

查看资源状态也分为同步和异步

同步查看资源状态

语法

fs.statSync(path[, options])
  • path 文件夹路径
  • options 选项配置( 可选 )

示例

const data = fs.statSync('../fs');
console.log('data', data);

效果如下:

image.png

从上述打印信息可以看出,这个方法可以获取资源的大小,创建时间,修改时间等等。

异步查看资源状态

语法

fs.statSync(path[, options], callback)
  • path 文件夹路径
  • options 选项配置( 可选 )
  • callback 操作后的回调

示例

fs.stat('../fs', (err, data) => {
  console.log('err', err);
  if (err) throw err;
  console.log('data', data);
})

效果如下:

image.png

4. 文件的删除

文件的删除也是区分同步和异步

同步删除

语法

fs.unlinkSync(path)
  • path: 文件路径

示例

fs.unlinkSync('./test.txt');

效果如下:

image.png

异步删除

语法

fs.unlink(path, callback)
  • path: 文件路径
  • callback: 回调函数

示例

fs.unlink('./test.txt', (err, data) => {
  console.log('err', err);
  console.log('data', data);
})

效果如下:

image.png

5. 文件的移动和重命名

文件的移动和重命名都是采用rename方法来实现的,也分为同步和异步

同步移动和重命名

语法

fs.renameSync(oldPath, newPath)
  • oldPath 文件当前的路径
  • newPath 文件新的路径

示例

// 重命名
fs.renameSync('./test.txt', './fs.txt');

效果如下:

image.png

// 移动
fs.renameSync('./fs.txt', './test/fs.txt');

效果如下:

image.png

异步移动和重命名

语法

fs.rename(oldPath, newPath, callback)
  • oldPath 文件当前的路径
  • newPath 文件新的路径
  • callback 操作后的回调

示例

// 重命名
fs.rename('./test/fs.txt', './test/test.txt', (err, data) => {
  console.log('err', err);
  if (err) throw err;
  console.log('data', data);
})

效果如下:

image.png

image.png

// 移动
fs.rename('./test/test.txt', './test.txt', (err, data) => {
  console.log('err', err);
  if (err) throw err;
  console.log('data', data);
})

效果如下:

image.png

image.png

6. 文件夹的操作

文件夹的操作包括创建文件夹,读取文件夹,删除文件夹

6.1 创建文件夹

同步创建

语法

fs.mkdirSync(path[, options])
  • path 文件夹路径
  • options 选项配置( 可选 )

示例

fs.mkdirSync('./test');

效果如下:

image.png

异步创建

语法

fs.mkdir(path[, options], callback)
  • path 文件夹路径
  • options 选项配置( 可选 )
  • callback: 回调函数

示例

fs.mkdir('./test1', (err, data) => {
  console.log('err', err);
  if (err) throw err;
  console.log('data', data);
})

效果如下:

image.png

image.png

6.2 读取文件夹

读取文件夹也分为同步和异步。

同步读取

语法

fs.readdirSync(path[, options])
  • path 文件夹路径
  • options 选项配置( 可选 ) 示例
const data = fs.readdirSync('./test');
console.log('data', data);

效果如下:

image.png

异步读取

语法

fs.readdir(path[, options], callback)
  • path 文件夹路径
  • options 选项配置( 可选 )
  • callback: 回调函数

示例

fs.readdir('./test1', (err, data) => {
  console.log('err', err);
  if (err) throw err;
  console.log('data', data);
})

效果如下:

image.png

6.3 删除文件夹

删除文件也分为同步和异步

同步删除

语法

fs.rmdirSync(path[, options])
  • path 文件夹路径
  • options 选项配置( 可选 )

示例

fs.rmdirSync('./test');

效果如下:

image.png

异步删除

语法

fs.rmdir(path[, options], callback)
  • path 文件夹路径
  • options 选项配置( 可选 )
  • callback: 回调函数

示例

fs.rmdir('./test1', (err, data) => {
  console.log('err', err);
  if (err) throw err;
  console.log('data', data);
})

效果如下:

image.png

想了解更多关于fs模块的内容,请查阅Node官网