Node.js 的文件系统模块(fs 模块)提供了丰富的 API,用于读取、写入、删除文件以及执行其他文件系统操作。
fs 模块既支持同步方法也支持异步方法,使得开发者可以根据具体需求选择合适的方式来处理文件操作。
Node.js 文件系统(fs 模块)模块中的方法均有异步和同步版本,例如读取文件内容的函数有异步的 fs.readFile()
和同步的 fs.readFileSync()
。
异步的方法函数最后一个参数为回调函数,回调函数的第一个参数包含了错误信息(error)。
建议大家使用异步方法,比起同步,异步方法性能更高,速度更快,而且没有阻塞。
var fs = require("fs")
var fs = require("fs");
// 异步读取
fs.readFile('input.txt', function (err, data) {
if (err) {
return console.error(err);
}
console.log("异步读取: " + data.toString());
});
// 同步读取
var data = fs.readFileSync('example.txt');
console.log("同步读取: " + data.toString());
console.log("程序执行完毕。");
方法 | 说明 |
---|---|
writeFile |
异步写入 |
writeFileSync |
同步写入 |
appendFile |
异步追加写入 |
appendFileSync |
同步追加写入 |
createWriteStream |
流式写入 |
fs.writeFile(file, data[, options], callback)
参数说明:
file
文件名data
待写入的数据options
选项设置 (可选)callback
写入回调fs.writeFile('example.txt', 'Hello, World!', (err) => {
if (err) {
console.error('Error writing file:', err);
return;
}
console.log('File written successfully');
});
fs.writeFileSync(file, data[, options])
参数与 fs.writeFile
大体一致,只是没有 callback
参数
try {
fs.writeFileSync('example.txt', 'Hello, World!');
console.log('File written successfully');
} catch (err) {
console.error('Error writing file:', err);
}
appendFile 作用是在文件尾部追加内容,appendFile 语法与 writeFile 语法完全相同
异步
fs.appendFile('example.txt', '\nAppending some text', (err) => {
if (err) {
console.error('Error appending to file:', err);
return;
}
console.log('Text appended successfully');
});
同步
try {
fs.appendFileSync('example.txt', '\nAppending some text');
console.log('Text appended successfully');
} catch (err) {
console.error('Error appending to file:', err);
}
fs.createWriteStream(path[, options])
参数说明:
path
文件路径options
选项配置( 可选 )const fs = require('fs');
const writableStream = fs.createWriteStream('output.txt');
writableStream.write('Hello, ');
writableStream.write('World!\n');
writableStream.end(); // 完成写入操作。此时可以关闭流或进行其他操作。
writableStream.on('finish', () => {
console.log('All writes are now complete.');
});
方法 | 说明 |
---|---|
readFile |
异步读取 |
readFileSync |
同步读取 |
createReadStream |
流式读取 |
fs.readFile(path[, options], callback)
参数说明:
path
文件路径options
选项配置callback
回调函数//导入 fs 模块
const fs = require('fs');
fs.readFile('./input.txt', (err, data) => {
if(err) throw err;
console.log(data);
});
fs.readFile('./input.txt', 'utf-8',(err, data) => {
if(err) throw err;
console.log(data);
});
fs.readFileSync(path[, options])
参数说明:
path
文件路径options
选项配置let data = fs.readFileSync('./input.txt');
let data2 = fs.readFileSync('./input.txt', 'utf-8');
fs.createReadStream(path[, options])
参数说明:
path
文件路径options
选项配置( 可选 )const fs = require('fs');
const readableStream = fs.createReadStream('large_file.txt', 'utf8');
readableStream.on('data', (chunk) => {
console.log('Received chunk:', chunk);
});
readableStream.on('end', () => {
console.log('No more data.');
});
异步
fs.unlink('example.txt', (err) => {
if (err) {
console.error('Error deleting file:', err);
return;
}
console.log('File deleted successfully');
});
同步
try {
fs.unlinkSync('example.txt');
console.log('File deleted successfully');
} catch (err) {
console.error('Error deleting file:', err);
}
借助 Node.js 的能力,我们可以对文件夹进行创建 、 读取 、 删除 等操作
方法 | 说明 |
---|---|
mkdir / mkdirSync |
创建文件夹 |
readdir / readdirSync |
读取文件夹 |
rmdir / rmdirSync |
删除文件夹 |
异步
fs.mkdir('new_directory', (err) => {
if (err) {
console.error('Error creating directory:', err);
return;
}
console.log('Directory created successfully');
});
同步
try {
fs.mkdirSync('new_directory');
console.log('Directory created successfully');
} catch (err) {
console.error('Error creating directory:', err);
}
异步
fs.readdir('new_directory', (err, files) => {
if (err) {
console.error('Error reading directory:', err);
return;
}
console.log('Directory contents:', files);
});
同步
try {
const files = fs.readdirSync('new_directory');
console.log('Directory contents:', files);
} catch (err) {
console.error('Error reading directory:', err);
}
//异步删除文件夹
fs.rmdir('new_directory', err => {
if(err) throw err;
console.log('删除成功');
});
//异步递归删除文件夹
fs.rmdir('new_directory', {recursive: true}, err => {
if(err) {
console.log(err);
}
console.log('递归删除')
});
//同步递归删除文件夹
fs.rmdirSync('new_directory', {recursive: true})
异步
fs.access('example.txt', fs.constants.F_OK, (err) => {
if (err) {
console.log('File does not exist');
} else {
console.log('File exists');
}
});
同步
try {
fs.accessSync('example.txt', fs.constants.F_OK);
console.log('File exists');
} catch (err) {
console.log('File does not exist');
}
fs.constants.F_OK
:检查文件或目录是否存在。fs.constants.R_OK
:检查文件或目录是否可读。fs.constants.W_OK
:检查文件或目录是否可写。fs.constants.X_OK
:检查文件或目录是否可执行。方法 | 说明 |
---|---|
stat |
异步查看资源信息 |
statSync |
同步查看资源信息 |
异步
fs.stat('example.txt', (err, stats) => {
if (err) {
console.error('Error getting stats:', err);
return;
}
// 查看资源是否为文件
console.log('Is file?', stats.isFile());
// 查看资源是否为目录
console.log('Is directory?', stats.isDirectory());
// 资源的大小
console.log('Size:', stats.size);
});
同步
try {
const stats = fs.statSync('example.txt');
console.log('Is file?', stats.isFile());
console.log('Is directory?', stats.isDirectory());
console.log('Size:', stats.size);
} catch (err) {
console.error('Error getting stats:', err);
}
在 Node.js 中,我们可以使用 rename
或 renameSync
来移动或重命名文件或文件夹
fs.rename(oldPath, newPath, callback)
fs.renameSync(oldPath, newPath)
参数说明:
oldPath
文件当前的路径newPath
文件新的路径callback
操作后的回调异步
fs.rename('./file.txt', './path/new_file.txt', (err) =>{
if(err) throw err;
console.log('移动完成')
});
同步
fs.renameSync('./file.txt', './path/new_file.txt');
以下为在异步模式下打开文件的语法格式:fs.open(path, flags[, mode], callback)
参数使用说明如下:
path
:文件的路径。flags
:文件打开的行为。具体值详见下文。mode
:设置文件模式(权限),文件创建默认权限为 0666(可读,可写)。callback
:回调函数,带有两个参数如:callback(err, fd)
。var fs = require('fs')
fs.open('package.json','r',(err,fd) => {
if (err) {
console.error(err)
}
})
flags 参数可以是以下值:
Flag | 描述 |
---|---|
r |
以只读模式打开文件。文件必须存在。如果文件不存在,会抛出异常 |
r+ |
以读写模式打开文件。文件必须存在。 |
rs |
以同步方式只读打开文件。阻塞操作,但在某些操作系统上可能会提供更好的稳定性。 |
rs+ |
以同步方式读写打开文件。阻塞操作,但在某些操作系统上可能会提供更好的稳定性。 |
w |
以只写模式打开文件。如果文件不存在则创建文件,如果文件存在则截断文件。 |
wx |
类似于 'w',但如果路径存在,则失败。 |
w+ |
以读写模式打开文件。如果文件不存在则创建文件,如果文件存在则截断文件。 |
wx+ |
类似于 'w+',但如果路径存在,则失败。 |
a |
以追加模式打开文件。如果文件不存在则创建文件。 |
ax |
类似于 'a',但如果路径存在,则失败。 |
a+ |
以读取和追加模式打开文件。如果文件不存在则创建文件。 |
ax+ |
类似于 'a+',但如果路径存在,则失败。 |
fs.read(fd[, options], callback)
fs.read(fd, buffer, offset, length, position, callback)
fs.read(fd, buffer[, options], callback)
参数使用说明如下:
fd
:通过 fs.open()
方法返回的文件描述符。buffer
:数据写入的缓冲区。offset
:缓冲区写入的写入偏移量。length
:要从文件中读取的字节数。position
:文件读取的起始位置,如果 position
的值为 null,则会从当前文件指针的位置读取。callback
:回调函数,有三个参数err
, bytesRead
, buffer
,err
为错误信息, bytesRead
表示读取的字节数,buffer
为缓冲区对象。var fs = require("fs");
var buf = new Buffer.alloc(1024);
console.log("准备打开已存在的文件!");
fs.open('input.txt', 'r+', function(err, fd) {
if (err) {
return console.error(err);
}
console.log("文件打开成功!");
console.log("准备读取文件:");
fs.read(fd, buf, 0, buf.length, 0, function(err, bytes){
if (err){
console.log(err);
}
console.log(bytes + " 字节被读取");
// 仅输出读取的字节
if(bytes > 0){
console.log(buf.slice(0, bytes).toString());
}
});
});
fs.write(fd, buffer[, options], callback)
var fs = require('fs')
fs.open('input.txt','w',(err,fd) => {
if (err) {
console.error(err)
}
fs.write(fd,Buffer.from('hello world'),(err,written) => {
console.log(written + " 字节被写入")
fs.close(fd)
})
})
注意:fs.close()
用于关闭由 fs.open
打开的文件描述符,如果文件描述符未正确关闭,会导致资源泄漏,最终耗尽可用的文件描述符,使程序无法打开新的文件或网络连接。另外我们一直说Buffer
叫缓冲区,它并不是真正的磁盘,我们只有在关闭文件转换才会写入,这样能够避免文件丢失。
对文件进行监视,并且在监视到文件被修改时执行处理
fs.watchFile(filename, [options], listener)
filename
,:完整路径及文件名;
options
:persistent:true
表示持续监视,不退出程序;interval
单位毫秒,表示每隔多少毫秒监视一次文件
listener
:文件发生变化时回调,有两个参数:curr
为一个fs.Stat
对象表示被修改后文件,prev
为一个fs.Stat
对象表示修改前对象
fs.watchFile(__dirname + '/test.txt', {interval: 20}, function (curr, prev) {
if(Date.parse(prev.ctime) == 0) {
console.log('文件被创建!');
} else if(Date.parse(curr.ctime) == 0) {
console.log('文件被删除!')
} else if(Date.parse(curr.mtime) != Date.parse(prev.mtime)) {
console.log('文件有修改');
}
});
fs.watchFile(__dirname + '/test.txt', function (curr, prev) {
console.log('这是第二个watch,监视到文件有修改');
});
fs.unwatchFile(filename, [listener])
filename
:完整路径及文件名;listener
: 要取消的监听器事件,如果不指定,则取消所有监听处理事件var listener = function (curr, prev) {
console.log('我是监视函数')
}
fs.unwatchFile(__dirname + '/test.txt', listener);
fs.watch(filename, [options], [listener]);
var fsWatcher = fs.watch(__dirname + '/test', function (event, filename) {
//console.log(event)
});
fsWatcher.on('change', function (event, filename) {
console.log(filename + ' 发生变化')
});
//30秒后关闭监视
setTimeout(function () {
console.log('关闭')
fsWatcher.close(function (err) {
if(err) {
console.error(err)
}
console.log('关闭watch')
});
}, 30000);