一、前言
fs
模块是 Node.js 内置的文件系统(File System)模块,它提供了一系列用于与文件系统进行交互的方法。通过fs
模块,可以对文件或目录进行读取、写入、删除、重命名、查询状态等操作,这使得 Node.js 能够很好地处理本地文件相关的任务。
二、常用方法
1. 读取文件
fs.readFile()
:这是一种异步读取文件内容的方法。它接受文件路径、编码方式(可选)和回调函数作为参数。例如:
const fs = require('fs');
const file_path = 'example.txt';
fs.readFile(file_path, 'utf8', (err, data) => {
if (err) {
console.error('读取文件出错:', err);
} else {
console.log('文件内容:', data);
}
});
在这个例子中,fs.readFile()
尝试以utf8
编码读取example.txt
文件。如果读取过程中出现错误,err
参数会包含错误信息,在回调函数中可以进行错误处理;如果读取成功,文件内容会存储在data
参数中并打印出来。
fs.readFileSync()
:这是fs.readFile()
的同步版本。它会阻塞 Node.js 进程,直到文件读取完成。例如:
const fs = require('fs');
const file_path = 'example.txt';
try {
const data = fs.readFileSync(file_path, 'utf8');
console.log('文件内容:', data);
} catch (err) {
console.error('读取文件出错:', err);
}
这里使用try - catch
块来捕获可能出现的错误。由于是同步操作,代码的执行顺序比较直观,在读取大文件时可能会导致程序暂时无响应,因为它会等待文件读取完成。
2. 写入文件
fs.writeFile()
:用于异步地将数据写入文件。如果文件不存在,会创建一个新文件;如果文件已存在,则会覆盖原有内容。例如:
const fs = require('fs');
const file_path = 'new_example.txt';
const data = '这是要写入文件的内容';
fs.writeFile(file_path, data, 'utf8', (err) => {
if (err) {
console.error('写入文件出错:', err);
} else {
console.log('文件已成功写入');
}
});
这个例子中,将字符串data
以utf8
编码写入到new_example.txt
文件中。同样,通过回调函数处理写入过程中的错误或成功情况。(内容会被覆盖)
fs.writeFileSync()
:这是fs.writeFile()
的同步版本,会阻塞进程直到写入操作完成。例如:
const fs = require('fs');
const file_path = 'new_example.txt';
const data = '这是要写入文件的内容';
try {
fs.writeFileSync(file_path, data, 'utf8');
console.log('文件已成功写入');
} catch (err) {
console.error('写入文件出错:', err);
}
3. 追加文件内容
fs.appendFile()
:异步地将数据追加到文件末尾(这个解决了**fs.writeFile()**会覆盖前面内容的特点)。例如:
const fs = require('fs');
const file_path = 'append_example.txt';
const data = '这是要追加的内容';
fs.appendFile(file_path, data, 'utf8', (err) => {
if (err) {
console.error('追加文件内容出错:', err);
} else {
console.log('内容已成功追加到文件');
}
});
- 与
fs.writeFile()
不同的是,fs.appendFile()
不会覆盖原有文件内容,而是在文件末尾添加新内容。 **fs.appendFileSync()**
:这是fs.appendFile()
的同步版本,会阻塞进程进行追加操作。
4. 读取目录内容
fs.readdir()
:异步地读取目录中的文件和子目录列表。例如:
const fs = require('fs');
const dir_path = 'example_directory';
fs.readdir(dir_path, (err, files) => {
if (err) {
console.error('读取目录出错:', err);
} else {
console.log('目录中的文件和子目录:', files);
}
});
- 这个方法返回目录中的文件名和子目录名的数组。如果需要进一步了解每个文件或子目录的详细信息,可以结合其他方法,如
fs.stat()
来获取文件或目录的状态信息。 fs.readdirSync()
:这是fs.readdir()
的同步版本,会返回目录中的文件和子目录名的数组。
5. 检查文件或目录是否存在
fs.existsSync()
:这是一个同步方法,用于检查指定的文件或目录是否存在。例如:
const fs = require('fs');
const file_path = 'example.txt';
if (fs.existsSync(file_path)) {
console.log('文件存在');
} else {
console.log('文件不存在');
}
需要注意的是,在 Node.js 官方文档中,fs.exists()
(异步版本)已被废弃,推荐使用fs.existsSync()
(同步版本)或者其他替代方法,如fs.stat()
或fs.access()
来检查文件或目录的存在性。
6. 获取文件或目录的状态信息
fs.stat()
:异步地获取文件或目录的状态信息,包括文件大小、创建时间、修改时间、权限等。例如:
const fs = require('fs');
const fileOrDirectoryPath = 'example.txt';
fs.stat(fileOrDirectoryPath, (err, stats) => {
if (err) {
console.error('获取文件或目录状态出错:', err);
} else {
// 检查是文件还是目录
if (stats.isFile()) {
console.log('这是一个文件。');
console.log('文件大小为:', stats.size, '字节');
console.log('文件的创建时间为:', stats.birthtime);
console.log('文件的最后访问时间为:', stats.atime);
console.log('文件的最后修改时间为:', stats.mtime);
} else if (stats.isDirectory()) {
console.log('这是一个目录。');
console.log('目录中的文件数量(大致):', stats.nlink);
}
}
});
这里的stats
对象包含了许多关于文件或目录状态的属性,可以根据需要获取相应的信息。fs.statSync()
是其同步版本。
7. 文件流(Stream)相关操作(高级用法)
fs.createReadStream()
和fs.createWriteStream()
:这两个方法用于创建文件读取流和文件写入流,通过流的方式处理文件可以更高效地处理大型文件,避免一次性将整个文件内容加载到内存中。例如,复制一个文件:
const fs = require('fs');
const read_stream = fs.createReadStream('source_file.txt');
const write_stream = fs.createWriteStream('destination_file.txt');
read_stream.on('data', (chunk) => {
write_stream.write(chunk);
});
read_stream.on('end', () => {
write_stream.end();
console.log('文件复制完成');
});
在这个例子中,fs.createReadStream('source_file.txt')
创建了一个读取source_file.txt
文件的读取流,fs.createWriteStream('destination_file.txt')
创建了一个写入destination_file.txt
的写入流。当读取流有数据(read_stream.on('data',...)
)时,将数据块chunk
写入到写入流中。当读取流结束(read_stream.on('end',...)
)时,结束写入流操作,表示文件复制完成。这种方式在处理大型文件时,能够有效地利用内存,提高文件处理的效率。
前面我们写的那个简单的爬虫例子也是用到了fs.createWriteStream(),将爬虫爬到的图片下载到相应的目录下。