Appearance
Node.js 文件系统操作
Node.js提供了丰富的文件系统操作API,允许开发者直接与操作系统文件系统进行交互。
文件系统模块(fs)
Node.js的fs模块提供了文件系统操作的API,支持同步和异步操作。
导入fs模块
javascript
const fs = require('fs');
const fsPromises = require('fs').promises;
const path = require('path');
异步文件操作
读取文件
javascript
// 异步读取文件
fs.readFile('./data.txt', 'utf8', (err, data) => {
if (err) {
console.error('读取文件失败:', err);
return;
}
console.log('文件内容:', data);
});
// 使用Promise方式
const { readFile } = require('fs').promises;
async function readTextFile(filePath) {
try {
const data = await readFile(filePath, 'utf8');
console.log('文件内容:', data);
return data;
} catch (err) {
console.error('读取文件失败:', err);
throw err;
}
}
写入文件
javascript
// 异步写入文件
fs.writeFile('./output.txt', 'Hello, Node.js!', (err) => {
if (err) {
console.error('写入文件失败:', err);
return;
}
console.log('文件写入成功');
});
// 追加内容到文件
fs.appendFile('./log.txt', `${new Date().toISOString()} - 日志信息\n`, (err) => {
if (err) {
console.error('追加文件失败:', err);
return;
}
console.log('日志追加成功');
});
// 使用Promise方式
const { writeFile, appendFile } = require('fs').promises;
async function writeFiles() {
try {
await writeFile('./output.txt', 'Hello, World!');
await appendFile('./log.txt', '新日志条目\n');
console.log('文件操作完成');
} catch (err) {
console.error('文件操作失败:', err);
}
}
检查文件状态
javascript
// 检查文件是否存在和状态
fs.stat('./data.txt', (err, stats) => {
if (err) {
console.error('获取文件状态失败:', err);
return;
}
console.log('文件信息:', {
isFile: stats.isFile(),
isDirectory: stats.isDirectory(),
size: stats.size,
birthTime: stats.birthtime,
mtime: stats.mtime
});
});
// 使用Promise方式
const { stat } = require('fs').promises;
async function checkFile(filePath) {
try {
const stats = await stat(filePath);
if (stats.isFile()) {
console.log(`${filePath} 是一个文件`);
} else if (stats.isDirectory()) {
console.log(`${filePath} 是一个目录`);
}
return stats;
} catch (err) {
if (err.code === 'ENOENT') {
console.log(`${filePath} 不存在`);
} else {
console.error('检查文件失败:', err);
}
throw err;
}
}
同步文件操作
javascript
try {
// 同步读取文件
const data = fs.readFileSync('./data.txt', 'utf8');
console.log('文件内容:', data);
// 同步写入文件
fs.writeFileSync('./output.txt', '同步写入的内容');
// 同步检查文件状态
const stats = fs.statSync('./data.txt');
console.log('文件大小:', stats.size);
} catch (err) {
console.error('同步操作失败:', err);
}
目录操作
创建和删除目录
javascript
// 创建目录
fs.mkdir('./new-directory', { recursive: true }, (err) => {
if (err) {
console.error('创建目录失败:', err);
return;
}
console.log('目录创建成功');
});
// 读取目录内容
fs.readdir('./data', (err, files) => {
if (err) {
console.error('读取目录失败:', err);
return;
}
console.log('目录内容:', files);
});
// 删除目录
fs.rmdir('./temp-directory', (err) => {
if (err) {
console.error('删除目录失败:', err);
return;
}
console.log('目录删除成功');
});
// 使用Promise方式
const { mkdir, readdir, rmdir, rm } = require('fs').promises;
async function directoryOperations() {
try {
// 递归创建目录
await mkdir('./path/to/new/directory', { recursive: true });
// 读取目录
const files = await readdir('./data');
console.log('目录文件:', files);
// 删除目录(可以删除非空目录)
await rm('./temp-directory', { recursive: true, force: true });
console.log('目录操作完成');
} catch (err) {
console.error('目录操作失败:', err);
}
}
流式文件操作
读取流
javascript
const fs = require('fs');
// 创建读取流
const readStream = fs.createReadStream('./large-file.txt');
readStream.on('data', (chunk) => {
console.log(`接收到 ${chunk.length} 字节的数据`);
});
readStream.on('end', () => {
console.log('文件读取完成');
});
readStream.on('error', (err) => {
console.error('读取流错误:', err);
});
写入流
javascript
// 创建写入流
const writeStream = fs.createReadStream('./output.txt');
writeStream.write('第一行数据\n');
writeStream.write('第二行数据\n');
writeStream.end('最后一行数据\n');
writeStream.on('finish', () => {
console.log('写入完成');
});
管道操作
javascript
// 文件复制 - 使用管道
const readStream = fs.createReadStream('./source.txt');
const writeStream = fs.createWriteStream('./destination.txt');
readStream.pipe(writeStream);
// 处理错误
readStream.on('error', (err) => {
console.error('读取错误:', err);
});
writeStream.on('error', (err) => {
console.error('写入错误:', err);
});
writeStream.on('finish', () => {
console.log('复制完成');
});
高级文件操作
文件监听
javascript
// 监听文件变化
fs.watch('./config.json', (eventType, filename) => {
if (filename) {
console.log(`文件 ${filename} 发生了 ${eventType} 事件`);
}
});
// 更详细的监听
fs.watch('./data', { recursive: true }, (eventType, filename) => {
console.log(`事件类型: ${eventType}`);
console.log(`文件名: ${filename}`);
});
文件权限操作
javascript
// 更改文件权限
fs.chmod('./script.sh', 0o755, (err) => {
if (err) {
console.error('更改权限失败:', err);
return;
}
console.log('权限更改成功');
});
// 获取文件权限
fs.stat('./data.txt', (err, stats) => {
if (err) {
console.error('获取状态失败:', err);
return;
}
console.log('文件权限:', stats.mode);
});
实用工具函数
javascript
const fs = require('fs').promises;
const path = require('path');
// 递归读取目录
async function readDirRecursive(dir) {
const entries = await fs.readdir(dir, { withFileTypes: true });
const files = [];
for (const entry of entries) {
const fullPath = path.join(dir, entry.name);
if (entry.isDirectory()) {
const nestedFiles = await readDirRecursive(fullPath);
files.push(...nestedFiles);
} else if (entry.isFile()) {
files.push(fullPath);
}
}
return files;
}
// 安全写入文件(创建目录如果不存在)
async function safeWriteFile(filePath, data) {
const dir = path.dirname(filePath);
// 确保目录存在
await fs.mkdir(dir, { recursive: true });
// 写入文件
await fs.writeFile(filePath, data);
}
// 复制文件
async function copyFile(src, dest) {
const readStream = require('fs').createReadStream(src);
const writeStream = require('fs').createWriteStream(dest);
return new Promise((resolve, reject) => {
readStream.pipe(writeStream);
writeStream.on('finish', resolve);
writeStream.on('error', reject);
readStream.on('error', reject);
});
}
// 检查路径是否存在
async function pathExists(filePath) {
try {
await fs.access(filePath);
return true;
} catch {
return false;
}
}
文件编码处理
javascript
// 处理不同编码的文件
const fs = require('fs');
// 读取二进制文件
fs.readFile('./image.jpg', (err, data) => {
if (err) throw err;
console.log('文件大小:', data.length, '字节');
});
// 读取UTF-8编码文件
fs.readFile('./text-utf8.txt', 'utf8', (err, data) => {
if (err) throw err;
console.log('UTF-8内容:', data);
});
// 读取Base64编码
fs.readFile('./file.txt', 'base64', (err, data) => {
if (err) throw err;
console.log('Base64编码:', data);
});
错误处理最佳实践
javascript
const fs = require('fs').promises;
async function robustFileOperation(filePath) {
try {
// 检查文件是否存在
await fs.access(filePath);
// 读取文件
const data = await fs.readFile(filePath, 'utf8');
return data;
} catch (err) {
switch (err.code) {
case 'ENOENT':
console.error('文件不存在:', filePath);
break;
case 'EACCES':
console.error('没有权限访问文件:', filePath);
break;
case 'EISDIR':
console.error('路径是一个目录,不是文件:', filePath);
break;
default:
console.error('文件操作失败:', err);
}
throw err;
}
}
Node.js的文件系统操作提供了强大而灵活的功能,可以满足各种文件处理需求。合理使用同步和异步操作,以及流式处理,可以构建高效、可靠的文件处理应用程序。