Node.js 中 fs 模块(非 Promise)API 详解
Node.js 的 fs 模块提供了同步和异步的文件系统操作。以下是非 Promise 版本的 API 详解:
1. 文件读取操作
const fs = require('fs');
// 异步读取文件
fs.readFile('file.txt', 'utf8', (err, data) => {
if (err) {
console.error('读取文件失败:', err);
return;
}
console.log('文件内容:', data);
});
// 同步读取文件
try {
const data = fs.readFileSync('file.txt', 'utf8');
console.log('文件内容:', data);
} catch (err) {
console.error('读取文件失败:', err);
}
// 使用文件描述符读取
fs.open('file.txt', 'r', (err, fd) => {
if (err) {
console.error('打开文件失败:', err);
return;
}
const buffer = Buffer.alloc(100);
fs.read(fd, buffer, 0, 100, 0, (err, bytesRead, buffer) => {
if (err) {
console.error('读取文件失败:', err);
fs.close(fd, () => {});
return;
}
console.log('读取字节数:', bytesRead);
console.log('文件内容:', buffer.toString());
fs.close(fd, (err) => {
if (err) console.error('关闭文件失败:', err);
});
});
});
2. 文件写入操作
// 异步写入文件
fs.writeFile('output.txt', 'Hello World', 'utf8', (err) => {
if (err) {
console.error('写入文件失败:', err);
return;
}
console.log('写入文件成功');
});
// 同步写入文件
try {
fs.writeFileSync('output.txt', 'Hello World', 'utf8');
console.log('写入文件成功');
} catch (err) {
console.error('写入文件失败:', err);
}
// 追加内容
fs.appendFile('log.txt', 'New log entry\n', 'utf8', (err) => {
if (err) {
console.error('追加内容失败:', err);
return;
}
console.log('追加内容成功');
});
// 使用文件描述符写入
fs.open('file.txt', 'w', (err, fd) => {
if (err) {
console.error('打开文件失败:', err);
return;
}
fs.write(fd, 'Hello World', 0, 'utf8', (err, written, string) => {
if (err) {
console.error('写入文件失败:', err);
fs.close(fd, () => {});
return;
}
console.log('写入字节数:', written);
fs.close(fd, (err) => {
if (err) console.error('关闭文件失败:', err);
});
});
});
3. 文件操作
// 复制文件
fs.copyFile('source.txt', 'dest.txt', (err) => {
if (err) {
console.error('复制文件失败:', err);
return;
}
console.log('复制文件成功');
});
// 重命名文件
fs.rename('old.txt', 'new.txt', (err) => {
if (err) {
console.error('重命名文件失败:', err);
return;
}
console.log('重命名文件成功');
});
// 删除文件
fs.unlink('file.txt', (err) => {
if (err) {
console.error('删除文件失败:', err);
return;
}
console.log('删除文件成功');
});
// 创建硬链接
fs.link('source.txt', 'link.txt', (err) => {
if (err) {
console.error('创建硬链接失败:', err);
return;
}
console.log('创建硬链接成功');
});
// 创建符号链接
fs.symlink('target.txt', 'symlink.txt', (err) => {
if (err) {
console.error('创建符号链接失败:', err);
return;
}
console.log('创建符号链接成功');
});
// 读取符号链接
fs.readlink('symlink.txt', (err, linkString) => {
if (err) {
console.error('读取符号链接失败:', err);
return;
}
console.log('符号链接目标:', linkString);
});
// 获取文件信息
fs.stat('file.txt', (err, stats) => {
if (err) {
console.error('获取文件信息失败:', err);
return;
}
console.log('Is file:', stats.isFile());
console.log('Size:', stats.size);
console.log('Created:', stats.birthtime);
console.log('Modified:', stats.mtime);
});
// 修改文件权限
fs.chmod('file.txt', 0o666, (err) => {
if (err) {
console.error('修改文件权限失败:', err);
return;
}
console.log('修改文件权限成功');
});
// 修改文件所有者
fs.chown('file.txt', 1000, 1000, (err) => {
if (err) {
console.error('修改文件所有者失败:', err);
return;
}
console.log('修改文件所有者成功');
});
4. 目录操作
// 创建目录
fs.mkdir('new-directory', { recursive: true }, (err) => {
if (err) {
console.error('创建目录失败:', err);
return;
}
console.log('创建目录成功');
});
// 读取目录
fs.readdir('directory', (err, files) => {
if (err) {
console.error('读取目录失败:', err);
return;
}
console.log('目录内容:', files);
});
// 删除目录
fs.rmdir('empty-directory', (err) => {
if (err) {
console.error('删除目录失败:', err);
return;
}
console.log('删除目录成功');
});
// 递归删除目录
fs.rm('directory', { recursive: true, force: true }, (err) => {
if (err) {
console.error('递归删除目录失败:', err);
return;
}
console.log('递归删除目录成功');
});
// 获取目录信息
fs.stat('directory', (err, stats) => {
if (err) {
console.error('获取目录信息失败:', err);
return;
}
console.log('Is directory:', stats.isDirectory());
});
// 修改目录权限
fs.chmod('directory', 0o755, (err) => {
if (err) {
console.error('修改目录权限失败:', err);
return;
}
console.log('修改目录权限成功');
});
5. 文件监视
// 监视文件变化
const watcher = fs.watch('file.txt', (eventType, filename) => {
console.log(`Event: ${eventType}, File: ${filename}`);
});
// 停止监视
watcher.close();
// 监视目录
const dirWatcher = fs.watch('directory', { recursive: true }, (eventType, filename) => {
console.log(`Directory event: ${eventType}, File: ${filename}`);
});
// 停止目录监视
dirWatcher.close();
6. 文件流操作
// 创建读取流
const readStream = fs.createReadStream('input.txt', {
encoding: 'utf8',
highWaterMark: 64 * 1024 // 64KB 缓冲区
});
// 创建写入流
const writeStream = fs.createWriteStream('output.txt', {
encoding: 'utf8',
flags: 'a'
});
// 流事件处理
readStream.on('data', (chunk) => {
console.log('Received chunk:', chunk);
});
readStream.on('end', () => {
console.log('Finished reading');
});
readStream.on('error', (error) => {
console.error('Read error:', error);
});
// 管道操作
readStream.pipe(writeStream);
// 关闭流
readStream.destroy();
writeStream.end();
7. 临时文件操作
// 创建临时目录
fs.mkdtemp('prefix-', (err, folder) => {
if (err) {
console.error('创建临时目录失败:', err);
return;
}
console.log('临时目录:', folder);
// 在临时目录中创建文件
const tempFile = path.join(folder, 'temp.txt');
fs.writeFile(tempFile, 'Temporary content', (err) => {
if (err) {
console.error('创建临时文件失败:', err);
return;
}
console.log('临时文件创建在:', tempFile);
});
});
8. 文件系统信息
// 获取文件系统信息
fs.statfs('/', (err, stats) => {
if (err) {
console.error('获取文件系统信息失败:', err);
return;
}
console.log('Total space:', stats.blocks * stats.bsize);
console.log('Free space:', stats.bfree * stats.bsize);
});
// 获取文件描述符
fs.open('file.txt', 'r', (err, fd) => {
if (err) {
console.error('打开文件失败:', err);
return;
}
console.log('File descriptor:', fd);
fs.close(fd, (err) => {
if (err) console.error('关闭文件失败:', err);
});
});
9. 错误处理
// 检查文件是否存在
fs.access('nonexistent.txt', fs.constants.F_OK, (err) => {
if (err) {
if (err.code === 'ENOENT') {
console.log('文件不存在');
} else if (err.code === 'EACCES') {
console.log('没有访问权限');
} else {
console.error('其他错误:', err);
}
} else {
console.log('文件存在');
}
});
10. 常量
// 文件打开模式
const modes = {
READ: fs.constants.O_RDONLY,
WRITE: fs.constants.O_WRONLY,
READ_WRITE: fs.constants.O_RDWR,
APPEND: fs.constants.O_APPEND,
CREATE: fs.constants.O_CREAT,
EXCL: fs.constants.O_EXCL,
TRUNC: fs.constants.O_TRUNC
};
// 文件类型
const types = {
FILE: fs.constants.S_IFREG,
DIRECTORY: fs.constants.S_IFDIR,
SYMBOLIC_LINK: fs.constants.S_IFLNK,
SOCKET: fs.constants.S_IFSOCK,
CHARACTER_DEVICE: fs.constants.S_IFCHR,
BLOCK_DEVICE: fs.constants.S_IFBLK,
FIFO: fs.constants.S_IFIFO
};
这些是 Node.js fs 模块(非 Promise 版本)的主要 API。与 Promise 版本相比,这些 API 使用回调函数而不是返回 Promise。