在Node.js中,fs
模块提供了多种方法来写入和读取文件,使得数据的持久性保存变得简单。下面将介绍几种常用的文件写入方法,包括异步、同步写入、追加写入和流式写入,及异步读取、同步读取、流式读取等文件读取方法。
首先,在使用写入和读取功能前,我们需要导入fs
模块,这是所有文件操作的基础:
const fs = require("fs");
一、文件写入
1. 异步写入
使用fs.writeFile
方法异步写入文件。例如,写入一个三字经文件:
fs.writeFile("./三字经.txt", "人之初,性本善。", (err) => {
if (err) {
console.log("写入失败");
return;
}
console.log("写入成功");
});
console.log("异步写入操作已发起");
注意:console.log("异步写入操作已发起");
会在 writeFile
回调之前执行,因为 writeFile
是异步的。
2. 同步写入
如果需要同步执行,可以使用fs.writeFileSync
方法:
try {
fs.writeFileSync("./data.txt", "text");
console.log("同步写入成功");
} catch (err) {
console.error("同步写入错误:", err);
}
console.log("同步写入操作已完成");
这里的console.log("
同步写入操作已完成");
会在writeFile
回调之后执行,因为writeFileSync
是同步的。
3. 异步追加写入
使用fs.appendFile
方法可以异步追加内容到文件末尾:
fs.appendFile("./三字经.txt", "性相近,习相远。", (err) => {
if (err) {
console.log("追加失败");
return;
}
console.log("追加成功");
});
4、同步追加写入
同样,fs.appendFileSync
方法用于同步追加写入:
try {
fs.appendFileSync("./data.txt", "\r\n追加text");
console.log("同步追加成功");
} catch (err) {
console.error("同步追加错误:", err);
}
5. 使用fs.writeFile
实现追加写入
通过设置flag: 'a'
选项,fs.writeFile
也可以用于追加写入:
fs.writeFile("./三字经.txt", "\r\n苟不教,父之过。", { flag: 'a' }, (err) => {
if (err) {
console.error("追加写入失败:", err);
return;
}
console.log("追加写入成功");
});
6. 流式写入
对于大文件或需要持续写入的数据,使用流(stream)是一个更好的选择。使用fs.
createWriteStream创建一个写入流并写入数据:
const ws = fs.createWriteStream('./静夜思.txt');
ws.write('窗前明月光,\r\n');
ws.write("疑是地上霜。\r\n");
ws.write("举头望明月,\r\n");
ws.write("低头思故乡。\r\n");
// 关闭流,确保数据完全写入文件
ws.end(() => {
console.log("流式写入完成");
});
//ws.close()
通常不需要显式调用ws.close()
来关闭写入流,因为close
方法不会等待数据被刷新到磁盘,可能会导致数据未完全写入文件。
可以使用ws.end()
,它会在数据写入完成后自动关闭流,确保数据完全写入文件。。
二、文件读取
1、异步读取
使用fs.readFile
方法可以异步读取文件内容。异步读取不会阻塞事件循环,这对于需要处理大量I/O操作的Node.js应用至关重要:
// 异步读取 radFile(这里以 "三字经.txt" 为例)
fs.readFile("./三字经.txt", (err, data) => {
if (err) {
console.log("读取失败");
return;
}
console.log(data.toString());
});
2、同步读取
使用fs.readFileSync
方法可以实现文件的同步读取。但请注意,同步读取会阻塞事件循环,直到文件读取完成。因此,在实际应用中,尤其是服务器应用中,通常不推荐使用同步读取:
// 同步读取 radFileSync(这里以 "三字经.txt" 为例)
let data = fs.readFileSync("./三字经.txt");
console.log(data.toString());
3、流式读取
流式读取更加灵活高效,它可以逐块读取文件内容,而不是一次性将整个文件加载到内存中。这对于处理大文件非常有用
使用 fs.createReadStream
方法可以创建一个可读流。
// 流式读取 createReadStream(这里以 "三字经.txt" 为例)
const rs = fs.createReadStream('./三字经.txt');
// 绑定data事件,每次读取到数据块时触发
rs.on('data', chunk => {
console.log(chunk);
// chunk 是一个 Buffer 对象,代表读取到的数据块
// 处理文本文件时,可将Buffer对象转换为字符串:chunk.toString()
});
// 绑定end事件,读取完成时触发
rs.on('end', () => {
console.log("读取完成");
});
// 绑定error事件,读取过程中发生错误时触发
rs.on('error', err => {
console.error("读取错误:", err);
});
建议至少绑定 error
事件来避免未捕获的异常导致程序崩溃