Node.js中fs模块详解

发布于:2025-04-13 ⋅ 阅读:(23) ⋅ 点赞:(0)

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。