Node.js学习记录(三)--- fs模块
Node.js fs模块是用于文件系统操作的核心工具,提供同步和异步两种文件操作方法。fs/promises模块提供Promise风格的API,支持async/await语法,提高了代码可读性和可维护性。
一、fs 模块
fs(File System)模块是Node.js常用的内置模块之一,用于操作文件系统,是Node.js与文件系统交互的核心工具。它提供了一系列方法来对文件/目录进行操作,且所有方法都存在同步和异步两个版本,可按需选择对应的方法。
Node.js 还针对异步方法提供了 fs/promises 模块,支持 Promise 语法、async/await,代码可读性和可维护性更好。
二、文件操作
1、文件读取
就是通过代码读取文件,获取文件中的数据,常用方法有异步读取、同步读取和流式读取三种:
① readFile(异步读取)
该方法用于异步的读取指定文件的全部内容。
具体语法:
fs.readFile(path[, options], callback)
,其中:
- path:表示要读取文件的路径,参数值可以是相对路径、绝对路径、Buffer、URL等等。
- options(可选参数):表示读取配置项,参数值为字符串或对象。如果值为字符串形式,则表示指定读取文件结果的字符编码,如utf8;如果值为对象形式,则表示设置多个配置,配置项有:encoding(字符编码,决定读取结果的数据类型,值为 string 类型,默认值为null,不指定时返回Buffer对象)、flag(文件操作标志,值为 string 类型,默认值为 'r’表示读取)、signal(操作令牌,值为AbortController类型,用于中途终止读取)。
- callback:表示读取文件的回调函数,函数接收两个参数:err、data,err表示读取失败时的错误信息,成功时为null,data表示读取的文件内容,数据类型取决于 encoding 的值,默认类型为 Buffer,如果指定encoding的为 utf8、base64等类型,则数据类型为字符串。
适用场景:
该方法会将整个文件内容加载到内存中,因此不适合处理大文件,适合读取小文件,如配置文件、简单静态资源等等。并且由于该方法是异步的,不会阻塞后续代码执行,所以还适合高并发场景。
案例代码:
// fs 使用示例
const fs = require('fs');
// 回调
fs.readFile('./demo.txt', (err, data) => {
if (err) {
// I/O错误、文件不存在、权限不足都会走这里
console.error('读取失败:', err);
return;
}
// 未指定字节编码 默认返回值为buffer类型
console.log('文件内容:', data);
});
// fs/promises 使用示例
const fs = require('fs/promises');
// 支持 async/await语法
async function readFileAsync() {
try {
const data = await fs.readFile('example.txt', 'utf8');
console.log(data);
} catch (err) {
console.error('读取失败:', err);
}
}
readFileAsync();
② readFileSync(同步读取)
该方法用于同步的读取指定文件的全部内容,但读取过程会阻塞后续代码执行,直到文件全部读取完成。如果读取过程中发生错误,该方法会直接抛出异常,因此常常结合 try/catch 使用。
具体语法:
fs.readFileSync(path[, options])
,参数与readFile()
中的对应参数相同。
适用场景:
该方法的适用场景与 readFile()
方法类似,但由于该方法是同步的,会阻塞后续代码执行,所以还适用于对执行顺序有严格要求、非高并发的场景。
案例代码:
const fs = require('fs');
try {
// 指定了字符编码
const data = fs.readFileSync('file.txt', 'utf8');
console.log(data); // 输出文件内容(字符串)
} catch (err) {
console.error('读取文件出错:', err);
}
③ createReadStream(流式读取)
该方法用于创建一个可读流,通过流式方式逐步一个片段一个片段将指定文件的内容读取出来。
具体语法:
fs.createReadStream(path[, options])
,其中:
- path:表示要读取文件的路径,参数值可以是相对路径、绝对路径、Buffer、URL等等。
- options(可选参数):表示读取配置项,参数值为字符串或对象。如果值为字符串形式,则表示指定读取文件结果的字符编码,如 utf8;如果值为对象形式,则表示设置多个配置,常用配置项有:encoding(字符编码,决定读取结果的数据类型,值为 string 类型,默认值为null,不指定时返回Buffer对象)、flag(文件操作标志,值为 string 类型,默认值为 ‘r’ ,表示读取)、signal(操作令牌,值为AbortController类型,用于中途终止读取)、highWaterMark(缓冲区大小,指定每次读取的数据大小,值为 integer 类型,单位为字节,默认值为64 * 1024,表示每次读取64kb)、start和end(指定读取文件的字节范围,包含start和end,值为 integer 类型,start默认值为0,end默认值为Infinity,表示读取文件全部字节)。
该方法返回一个 ReadStream 对象,需要结合事件监听方法(on)使用,常用事件有:
- open:在文件被打开时触发。
- data:在文件读取过程中,每读取一个数据片段,都会触发一次 data 事件。
- end:在文件所有数据读取完毕后触发。
- error:在文件读取过程中,出现错误时触发。
- close:在流和文件描述符都关闭时触发。
适用场景:
该方法是分块读取文件,特别适合处理大文件,控制好 highWaterMark 的值,增大该属性值,会提高读取速度,但会增加内存占用,减小该属性的值,则会减少内存占用,但读取速度也会变慢。对于I/O密集型任务,通常会适当的增大 highWaterMark 的值。
但该方法存在背压问题:使用该方法读取文件数据,然后将数据进行处理或写入其他地方。如果此时写入速度跟不上读取速度,则数据会在缓冲区堆积,导致内存占用过多。该问题可以配合管道(pipe()
)使用,管道会自动处理背压。
案例代码:
const fs = require('fs');
// 创建可读流
const readStream = fs.createReadStream('example.txt', {
encoding: 'utf8',
highWaterMark: 1024 // 1KB 缓冲区
});
// 监听 data 事件
readStream.on('data', (chunk) => {
console.log('读取到数据块:');
console.log(chunk);
});
// 监听 end 事件
readStream.on('end', () => {
console.log('文件读取完成');
});
// 监听 error 事件
readStream.on('error', (err) => {
console.error('读取文件时发生错误:', err);
});
2、文件写入/创建
就是通过代码将数据写入到文件中,常用方法有异步写入、同步写入、追加写入和流式写入四类:
① writeFile(异步写入/创建)
该方法用于异步的将数据写入指定文件,如果指定文件已存在,则会覆盖文件中的内容,如果指定文件不存在,则会创建文件,并写入内容。
具体语法:
fs.writeFile(file, data[, options], callback)
,其中:
- file:表示要写入数据的文件,参数值可以是相对路径、绝对路径、Buffer、URL等等。
- data:表示要写入的数据,参数值可以是String、Buffer等等。
- options(可选参数):表示写入配置项,参数值为字符串或对象。如果值为字符串形式,则表示指定写入数据的字符编码,如 utf8;如果值为对象形式,则表示设置多个配置,常用配置项有:encoding(字符编码,值为 string 类型,默认值为utf8)、flag(文件操作标志,值为 string 类型,默认值为 ‘w’ ,表示写入)、signal(操作令牌,值为AbortController类型,用于中途终止读取)、mode(指定文件的权限模式,仅限于新创建的文件,值为 integer 类型,默认值为 0o666)。
- callback:表示写入文件的回调函数,函数接收一个参数:err,err表示读取失败时的错误信息,默认值为null。
适用场景:
该方法会将新数据覆盖掉文件的原始数据,因此适合创建文件并写入初始内容、完全替换文件内容等等。并且由于该方法是异步的,不会阻塞后续代码执行,所以还适合高并发场景。
案例代码:
// fs 使用示例
const fs = require('fs');
fs.writeFile('example.txt', 'Hello World', (err) => {
if (err) {
console.error('文件写入失败', err);
return;
};
console.log('文件写入成功');
});
// fs/promises 使用示例
const fs = require('fs/promises');
async function writeFileAsync() {
try {
await fs.writeFile('example.txt', 'Hello World', 'utf8');
console.log("写入成功");
} catch (err) {
console.error('写入失败:', err);
}
}
writeFileAsync();
② writeFileSync(同步写入/创建)
该方法用于同步的将数据写入指定文件,如果指定文件已存在,则会覆盖文件中的内容,如果指定文件不存在,则会创建文件,并写入内容。由于是同步操作,会阻塞后续代码执行直到写入完成。
如果写入过程中发生错误,该方法会直接抛出异常,因此常常结合 try/catch 使用。
具体语法:
fs.writeFileSync(file, data[, options])
,参数与writeFile()
中的对应参数相同。
适用场景:
该方法的适用场景与 writeFile()
方法类似,但由于是同步操作,会阻塞后续代码执行,所以还适用于对执行顺序有严格要求、非高并发的场景。
案例代码:
const fs = require('fs');
try {
// 同步写入文件
fs.writeFileSync('example.txt', "你好,世界", 'utf8');
console.log('文件写入成功');
} catch (err) {
// 捕获写入过程中可能出现的错误
console.error('文件写入失败:', err);
}
③ appendFile(异步追加写入/创建)
该方法用于异步的将数据追加写入到指定文件的末尾,如果指定文件已存在,则会在文件原有内容后添加新数据;如果指定文件不存在,则会创建文件,并写入内容。
具体语法:
fs.appendFile(file, data[, options], callback)
,其中:
- file:表示要追加写入数据的文件,参数值可以是相对路径、绝对路径、Buffer、URL等等。
- data:表示要追加写入的数据,参数值可以是String、Buffer等等。
- options(可选参数):表示写入配置项,参数值为字符串或对象。如果值为字符串形式,则表示指定写入数据的字符编码,如 utf8;如果值为对象形式,则表示设置多个配置,常用配置项有:encoding(字符编码,值为 string 类型,默认值为utf8)、flag(文件操作标志,值为 string 类型,默认值为 ‘w’ ,表示写入)、signal(操作令牌,值为AbortController类型,用于中途终止读取)、mode(指定文件的权限模式,仅限于新创建的文件,值为 integer 类型,默认值为 0o666)。
- callback:表示追加文件的回调函数,函数接收一个参数:err,err 表示操作失败时的错误信息,默认值为 null。
适用场景:
该方法不会覆盖文件的原有内容,只会在文件末尾添加新数据,因此适合记录日志、累加数据、补充文件内容等场景。而且由于该方法是异步的,不会阻塞后续代码执行,所以还适合高并发场景。
案例代码:
//fs 使用示例
const fs = require ('fs');
fs.appendFile ('example.txt', ' 追加的内容 ', (err) => {
if (err) {
console.error('数据追加失败', err);
return;
};
console.log (' 数据追加成功 ');
});
// fs/promises 使用示例
const fs = require ('fs/promises');
async function appendFileAsync () {
try {
await fs.appendFile ('example.txt', ' 通过 promises 追加的内容 ', 'utf8');
console.log ("追加成功");
} catch (err) {
console.error (' 追加失败:', err);
}
}
appendFileAsync ();
④ appendFileSync(同步追加写入)
该方法用于同步的将数据追加到指定文件的末尾,若指定文件已存在,新数据会添加到原有内容之后;若文件不存在,则会创建文件并写入数据。由于是同步操作,会阻塞后续代码执行直到写入完成。
如果追加写入过程中发生错误,该方法会直接抛出异常,因此常常结合 try/catch 使用。
具体语法:
fs.appendFileSync(file, data[, options])
,参数与appendFile()
中的对应参数相同。
适用场景:
该方法的适用场景与 appendFile()
类似,但由于是同步操作,会阻塞后续代码执行,所以还适用于对执行顺序有严格要求、非高并发的场景。
案例代码:
const fs = require ('fs');
try {
fs.appendFileSync ('example.txt', ' 同步追加的内容 ');
console.log (' 数据同步追加成功 ');
} catch (err) {
console.error (' 同步追加失败:', err);
}
⑤ createWriteStream(流式写入/创建)
该方法用于创建可写流,通过流式方式将数据逐步一个片段一个片段的写入指定文件。如果文件已存在,默认会覆盖原有内容;若文件不存在,则会创建文件后再进行写入。
具体语法:
fs.createWriteStream(path[, options])
,其中:
- path:表示要写入文件的路径,参数值可以是相对路径、绝对路径、Buffer、URL等等。
- options(可选参数):表示写入配置项,参数值为字符串或对象。如果值为字符串形式,则表示指定写入文件结果的字符编码,如 utf8;如果值为对象形式,则表示设置多个配置,常用配置项有:encoding(字符编码,值为 string 类型,默认值为 utf8)、flag(文件操作标志,值为 string 类型,默认值为 ‘w’ ,表示写入)、signal(操作令牌,值为AbortController类型,用于中途终止写入)、highWaterMark(缓冲区大小,指定每次写入的数据大小,值为 integer 类型,单位为字节,默认值为16 * 1024,表示每次写入16kb)、start(指定数据在文件中的起始写入位置,值为 integer 类型,默认值为0)、mode(指定文件的权限模式,仅限于新创建的文件,值为 integer 类型,默认值为 0o666)。
该方法返回一个 WriteStream 对象,需要结合事件监听方法(on)使用,常用事件有:
- open:在要写入的文件被打开时触发。
- ready:在流准备好可以写入数据时触发。
- finish:在所有数据都写入成功,且调用
end()
方法后触发。 - error:在写入过程中发生错误时触发。
- close:在流和文件描述符都关闭时触发。
适用场景:
该方法是分块写入数据,特别适合大文件的写入,控制好 highWaterMark 的值,避免一次性加载大量数据导致内存占用过高,增大该属性值,会提高写入速度,但会增加内存占用,减小该属性的值,则会减少内存占用,但写入速度也会变慢。
该方法可以与读取流(createReadStream()
)配合实现文件复制等操作,并结合管道(pipe)高效传输数据,还能自动处理背压问题。
案例代码:
const fs = require ('fs');
// 创建可写流
const ws = fs.createWriteStream(__dirname + '/data/example.txt', { encoding: 'utf8' });
// 监听open事件
ws.on('open', () => {
console.log('要写入的文件被打开');
});
// 监听ready事件
ws.on('ready', () => {
console.log('流准备好,可以写入数据');
});
// 分批次写入数据
for (let i = 0; i < 10; i++) {
ws.write(`这是第 ${i + 1} 行数据\n`)
}
// 结束写入
ws.end();
// 监听finish事件
ws.on('finish', () => {
console.log('所有数据写入成功');
});
// 监听error事件
ws.on('error', (err) => {
console.error(' 写入出错:', err);
});
// 监听close事件
ws.on('close', () => {
console.log('关闭');
});
3、文件移动/重命名
① rename(异步移动/重命名)
该方法用于异步的移动或重名命名文件/目录。如果目标路径与源路径在同一目录下,则结果为文件/目录重命名;如果在不同目录下,则结果为文件/目录移动,且可同时进行重命名。如果目标路径目录下存在同名文件,则会覆盖;如果目标路径目录下存在同名目录,则会报错。
具体语法:
fs.rename(oldPath, newPath, callback)
,其中:
- oldPath:源路径,表示要移动或重命名的文件/目录,参数值可以是相对路径和绝对路径、Buffer、URL 等。
- newPath:目标路径,表示文件/目录要移动到的位置及名称,参数值可以是相对路径和绝对路径、Buffer、URL 等 。如果目标路径存在同名目录,则会报错。
- callback:表示操作完成的回调函数,函数接收一个参数:err,err 表示操作失败时的错误信息,默认值为 null。
适用场景:
该方法适用于整理文件结构、重命名文件等场景。而且由于该方法是异步的,不会阻塞后续代码执行,所以还适合高并发场景。
案例代码:
// fs 使用示例(重命名文件)
const fs = require('fs');
// 将 example.txt 重命名为 newExample.txt
fs.rename('example.txt', 'newExample.txt', (err) => {
if (err) {
console.error('文件重命名失败', err);
return;
};
console.log('文件重命名成功');
});
// 将src目录下的example.txt 移动到 src2目录下 并命名为 moved.txt
fs.rename('./src/example.txt', '.src2/moved.txt', (err) => {
if (err) {
console.error('文件移动失败', err);
return;
};
console.log('文件移动成功');
});
// fs/promises 使用示例
const fs = require('fs/promises');
async function renameFileAsync() {
try {
// 重命名目录
await fs.rename('/test2', '/test');
console.log("目录重命名成功");
} catch (err) {
console.error('目录重命名失败:', err);
}
}
renameFileAsync();
② renameSync(同步移动/重命名)
该方法用于同步的移动或重命名文件/目录,具体功能与 rename()
完全一致。
如果移动或重命名过程中发生错误,该方法会直接抛出异常,因此常常结合 try/catch 使用。
具体语法:
fs.renameSync(oldPath, newPath)
,参数与rename()
中的对应参数相同。
适用场景:
该方法适用场景与rename()
方法类似,但是由于是同步操作,会阻塞后续代码执行,所以还适用于对执行顺序有严格要求、非高并发的场景。
案例代码:
// fs 使用示例
const fs = require('fs');
try {
// 同步重命名目录
fs.renameSync(__dirname + '/test', __dirname + '/test2');
console.log('文件同步重命名成功');
} catch (err) {
console.error('文件同步重命名失败:', err);
}
4、文件删除
① unlink(异步删除文件)
该方法用于异步的删除指定的文件,注意不能用于删除目录,否则会抛出错误。
具体语法:
fs.unlink(path[, options], callback)
,其中:
- path:表示要删除的文件路径,参数值可以是相对路径、绝对路径、Buffer、URL 等等。
- callback:表示删除文件的回调函数,函数接收一个参数:err,err 表示删除失败时的错误信息,默认值为 null。
适用场景:
该方法适用于删除单个文件,如后台清理临时文件等等。并且由于是异步操作,不会阻塞后续代码执行,所以还适合高并发场景。
案例代码:
// fs 使用示例
const fs = require('fs');
fs.unlink(__dirname + '/test/a.js', (err) => {
if (err) {
console.error('文件删除失败', err);
return;
};
console.log('文件删除成功');
});
// fs/promises 使用示例
const fs = require('fs/promises');
fs.unlink(__dirname + '/test/b.js').then(() => {
console.log("文件删除成功")
}).catch(err => {
console.log("文件删除失败")
});
② unlinkSync(同步删除文件)
该方法用于同步的删除指定的文件,具体功能与 unlink()
方法一致。
如果删除过程中发生错误,该方法会直接抛出异常,因此常常结合 try/catch 使用。
具体语法:
fs.unlinkSync(path)
,参数与 unlink()
中的对应参数相同。
适用场景:
该方法适用场景与unlink()
方法类似,但是由于是同步操作,会阻塞后续代码执行,所以还适用于对执行顺序有严格要求、非高并发的场景。
案例代码:
// fs 使用示例
const fs = require('fs');
try {
fs.unlinkSync('test.txt');
console.log('文件删除成功');
} catch (err) {
console.error('删除失败:', err);
}
5、文件信息查看
① stat(异步获取文件信息)
该方法用于异步的获取指定文件/目录的详细信息,包括大小、创建时间、修改时间、文件类型、权限模式等。
具体语法:
fs.stat(path[, options], callback)
,其中:
- path:表示要获取信息的文件/目录路径,参数值可以是相对路径、绝对路径、Buffer、URL 等等。
- options(可选参数):表示配置项,参数值为对象类型,常用配置项有:bigint(是否以 BigInt 类型返回文件信息中的数值字段,值为布尔类型,默认值为false)。
- callback:表示获取信息后的回调函数,函数接收两个参数:err(错误信息,获取失败时存在)和 stats(成功获取到的文件信息对象,包含文件的各种元数据)。
该方法成功后返回一个 Stats 对象,其中除了当前文件/目录的详细信息之外,还提供了一系列相关方法,常用方法有:
- stats.isDirectory():校验当前 stats 是否描述一个目录。
- stats.isFile():校验当前 stats 是否描述一个文件。
适用场景:
该方法适用于需要根据文件/目录信息判断进行不同处理的场景。并且由于是异步操作,不会阻塞后续代码执行,所以还适合高并发场景。
案例代码:
// fs 使用示例
const fs = require('fs');
fs.stat(__dirname + '/test', (err, stats) => {
if (err) {
console.error('获取目录信息失败', err);
return;
};
console.log('获取目录信息成功:', stats);
console.log('当前是否是文件:', stats.isFile());
});
// fs/promises 使用示例
const fs = require('fs/promises');
async function getFileStats() {
try {
const stats = await fs.stat(__dirname + '/test');
console.log('获取目录信息成功:', stats);
console.log('当前是否是目录:', stats.isDirectory());
} catch (err) {
console.error('获取目录信息失败:', err);
}
}
getFileStats();
② statSync(同步获取文件信息)
该方法用于同步的获取指定文件/目录的详细信息,具体功能与 stat
方法一致。
如果获取信息过程中发生错误,该方法会直接抛出异常,因此常常结合 try/catch 使用。
具体语法:
fs.stat(path[, options])
,参数与 stat()
中的对应参数相同,返回值同样是一个 Stats 对象。
适用场景:
该方法适用场景与stat()
方法类似,但是由于是同步操作,会阻塞后续代码执行,所以还适用于对执行顺序有严格要求、非高并发的场景。
案例代码:
const fs = require('fs');
try {
const stats = fs.statSync('test.txt');
console.log('获取文件信息成功:', stats);
} catch (err) {
console.error('获取文件信息失败:', err);
}
三、目录操作
除了上面提到的 rename/renameSync
和stat/statSync
这些同时能操作文件和目录的方法之外,fs 模块还提供了一些操作目录的方法。
1、创建目录
① mkdir(异步创建目录)
该方法用于异步的创建指定目录,前提是目录不存在,如果目录存在且未设置递归创建选项时,会报错;如果目录存在且设置了递归创建选项,则不会创建新的目录,但也不报错,会将之前存在的目录作为创建的目录。
具体语法:
fs.mkdir(path[, options], callback)
,其中:
- path:表示要创建的目录路径,参数值可以是相对路径、绝对路径、Buffer、URL 等等。
- options(可选参数):表示创建目录的配置项,参数值为整数或对象。如果值为整数形式,则表示指定目录的权限模式,等同于对象形式的 mode 属性;如果值为对象形式,则常用配置项有:recursive(是否递归创建目录,值为 boolean 类型,默认值为 false,设为 true 时可创建多级目录)、mode(指定目录的权限模式,值为 integer 类型,默认值为 0o777,在 Windows 系统中部分权限可能不生效)。
- callback:表示创建目录的回调函数,函数接收一个参数:err,err 表示创建失败时的错误信息,默认值为 null。
适用场景:
该方法适用于需要动态创建目录的常见,如调整文件目录等,配合 recursive: true
选项可以方便地创建多级目录结构。并且由于是异步操作,不会阻塞后续代码执行,所以还适合高并发场景。
案例代码:
// fs 使用示例
const fs = require('fs');
// 创建多级目录
fs.mkdir(__dirname + '/a/b/c', { recursive: true }, (err) => {
if (err) {
console.error('多级目录创建失败', err);
return;
};
console.log('多级目录创建成功');
});
// fs/promises 使用示例
const fs = require('fs/promises');
async function createDirAsync() {
try {
await fs.mkdir(__dirname + '/a/b/c', { recursive: true });
console.log("多级目录创建成功");
} catch (err) {
console.error('多级创建失败:', err);
}
}
createDirAsync();
② mkdirSync(同步创建目录)
该方法用于同步的创建指定目录,具体功能与 mkdir
方法一致。
如果获取信息过程中发生错误,该方法会直接抛出异常,因此常常结合 try/catch 使用。
具体语法:
fs.mkdir(path[, options])
,参数与 mkdir()
中的对应参数相同。
适用场景:
该方法适用场景与mkdir()
方法类似,但是由于是同步操作,会阻塞后续代码执行,所以还适用于对执行顺序有严格要求、非高并发的场景。
案例代码:
// fs 使用示例
const fs = require('fs');
try {
// 递归创建多级目录
fs.mkdirSync(__dirname + '/x/y/z', { recursive: true });
console.log('同步多级目录创建成功');
} catch (err) {
console.error('同步目录创建失败:', err);
}
2、读取目录
① readdir(异步读取目录)
该方法用于异步的读取指定目录的内容,返回目录中所有文件和子目录的名称列表(不包括 .
和 ..
),并可以通过配置选项,获取更详细的文件信息。
具体语法:
fs.readdir(path[, options], callback)
,其中:
- path:表示要读取的目录路径,参数值可以是相对路径、绝对路径、Buffer、URL 等。
- options(可选参数):表示读取配置项,参数值为字符串或对象,如果值是字符串,则表示以指定编码格式返回名称列表,如 utf8;如果值是对象,则表示设置多个配置,常用配置项有:encoding(名称列表的字符编码,值为 string 类型,默认值为utf8)、withFileTypes(是否返回具体文件信息,值为 boolean类型,默认值为 false ,如果设置为 true, 则方法返回文件和目录的 Dirent 对象列表)、recursive(是否递归读取子目录,Node v20+版本后支持,值为 boolean 类型,默认值为false;若设为 true,则会递归遍历所有子目录并返回完整路径)。
- callback:表示读取目录的回调函数,函数接受两个参数:err 和 files。err表示读取失败时的错误信息,默认值为null;files表示读取成功时返回的文件/目录列表,列表元素类型由 options 决定,默认为文件/子目录名称的字符串数组。
该方法设置withFileTypes: true
后返回的是 Dirent 对象列表,对象中包含文件/目录名等信息,并且还提供了一系列相关方法,常用方法有:
- dirent.isDirectory():校验当前 Dirent 是否描述一个目录。
- dirent.isFile():校验当前 Dirent 是否描述一个文件。
适用场景:
该方法适用于批量获取目录中的文件信息等场景。并且由于是异步操作,不会阻塞后续代码执行,所以还适合高并发场景。
案例代码:
// fs 使用示例
const fs = require('fs');
// 获取文件类型信息
fs.readdir(__dirname + '/test', { withFileTypes: true, }, (err, files) => {
if (err) {
console.error('获取目录下文件信息失败', err);
return;
};
files.forEach(file => {
if (file.isFile()) {
console.log(`文件: ${file.name}`);
} else if (file.isDirectory()) {
console.log(`目录: ${file.name}`);
}
});
});
// fs/promises 版本示例
const fs = require('fs/promises');
async function readDirRecursive() {
try {
const files = await fs.readdir(__dirname + '/test', { withFileTypes: true });
console.log('递归读取结果:', files); // 输出包含子目录文件的完整路径
} catch (err) {
console.error('读取失败:', err);
}
}
readDirRecursive();
② readdirSync(同步读取目录)
该方法用于同步的读取指定目录中的内容,具体功能与 readdir()
方法一致。
如果获取信息过程中发生错误,该方法会直接抛出异常,因此常常结合 try/catch 使用。
具体语法:
fs.readdirSync(path[, options])
,参数与 readdir()
中的对应参数相同。
适用场景:
该方法适用场景与readdir()
方法类似,但是由于是同步操作,会阻塞后续代码执行,所以还适用于对执行顺序有严格要求、非高并发的场景。
案例代码:
// 基础使用示例
const fs = require('fs');
try {
const files = fs.readdirSync(__dirname + '/test');
console.log('目录内容:', files);
} catch (err) {
console.error('读取失败:', err);
}
3、删除目录
① rmdir(异步删除目录)
该方法用于异步的删除指定的目录,默认只能删除空目录,如果目录不为空,则会抛出错误,但可以通过配置删除非空目录。
具体语法:
fs.rmdir(path[, options], callback)
,其中:
- path:表示要删除的目录路径,参数值可以是相对路径、绝对路径、Buffer、URL 等。
- optinos(可选参数):表示删除目录操作的配置项,参数值为对象,常用配置项有:recursive(是否递归删除目录,值为 boolean 类型,默认值为 false,设置为 true,则可以删除非空目录)、maxRetries(最大重试次数,表示删除失败时,重试的次数,值为 integer 类型,默认值为0。如果recursive值为false,则配置项会被忽略)、retryDelay(重试延迟时间,表示在删除失败重试时,延迟等待的时间。如果recursive值为false,则配置项会被忽略)。
- callback:表示删除目录操作的回调函数,函数接收一个参数:err,err 表示删除失败时的错误信息,默认值为 null。
适用场景:
该方法适用于删除某个目录及其内在文件等场景。并且由于是异步操作,不会阻塞后续代码执行,所以还适合高并发场景。
案例代码:
// fs 使用示例
const fs = require('fs');
// 递归删除非空目录
fs.rmdir(__dirname + '/a', { recursive: true }, (err) => {
if (err) {
console.error('非空目录删除失败', err)
return;
};
console.log('非空目录删除成功');
});
// fs/promises 使用示例
const fs = require('fs/promises');
async function removeDirAsync() {
try {
// 递归删除空目录
await fs.rmdir(__dirname + '/a');
console.log('空目录删除成功');
} catch (err) {
console.error('空目录删除失败:', err);
}
}
removeDirAsync();
② rmdirSync(同步删除目录)
该方法用于同步删除指定的目录,具体功能与 rmdir()
方法一致。
如果获取信息过程中发生错误,该方法会直接抛出异常,因此常常结合 try/catch 使用。
具体语法:
fs.rmdirSync(path[, options])
,参数与 rmdir()
中的对应参数相同。
适用场景:
该方法适用场景与rmdir()
方法类似,但是由于是同步操作,会阻塞后续代码执行,所以还适用于对执行顺序有严格要求、非高并发的场景。
案例代码:
// fs 使用示例
const fs = require('fs');
try {
// 删除空目录
fs.rmdirSync(__dirname + '/a');
console.log('空目录删除成功');
} catch (err) {
console.error('删除失败:', err);
}
请关注公众号,优先查看更多优质资源:
更多推荐
所有评论(0)