Node.js fs模块详解:文件权限、读写、目录操作与路径处理

作者:终端旅客时间:2026-10-30 18:12:06浏览:419

本文详细介绍Node.js中fs文件系统模块的核心功能,涵盖文件权限检测、状态获取、追加读写、基础读写、重命名删除、目录创建与递归处理以及绝对路径获取。通过同步与异步两种模式的代码示例,展示如何高效进行文件I/O操作,帮助开发者掌握Node.js文件处理的最佳实践。

Node.js fs模块概述

fs文件系统模块是Node.js中处理文件操作的核心模块,几乎所有文件相关的功能都依赖于它。该模块提供的API均包含同步和异步两种实现方式,下文将逐一介绍其具体用法。

文件权限检测

1、检测当前进程对文件的权限

使用fs.access(path[, mode], callback)方法可以检查调用进程对指定路径的访问权限。mode参数为整数,支持以下常量值:

  • fs.constants.F_OK:表示路径对调用进程可见,即文件存在。
  • fs.constants.R_OK:表示路径对应的文件可读。
  • fs.constants.W_OK:表示路径对应的文件可写。
  • fs.constants.X_OK:表示路径对应的文件可执行。

具体调用方式如下所示:


fs.access('./note.txt',fs.constants.F_OK,(err)=>{
console.log(err?'文件不存在':'文件已经存在');
});

同步版本在发生异常时会直接抛出错误,否则无返回值。由于同步方法会阻塞线程,建议结合try...catch语句使用,适用于所有同步API,示例如下:


try{
fs.accessSync('./note.txt',fs.constants.F_OK);
}catch(ex){
console.log('文件不存在');
}

获取文件状态

2、获取文件状态

通过fs.stat(path, callback)和fs.statSync(path)方法可以获取指定path的文件状态信息。回调函数包含(err, stats)两个参数,其中stats为fs.Stats对象,具备以下属性:


{ dev: 638212,
 mode: 33206,
 nlink: 1,
 uid: 0,
 gid: 0,
 rdev: 0,
 blksize: undefined,
 ino: 105553116266564850,
 size: 1094,
 blocks: undefined,
 atime: 2016-11-22T08:45:43.505Z,
 mtime: 2016-11-22T09:33:13.535Z,
 ctime: 2016-11-22T09:33:13.535Z,
 birthtime: 2016-11-22T08:45:43.505Z }

此外,stats对象还提供以下判断方法:


stats.isFile()
 stats.isDirectory()
 stats.isBlockDevice()
 stats.isCharacterDevice()
 stats.isSymbolicLink() (only valid with fs.lstat())
 stats.isFIFO()
 stats.isSocket()

具体使用示例如下:


fs.stat('./app.js',(err,stats)=>{
  if(err) throw err;
  console.log(stats);
});
var stats = fs.statSync('../test.txt');//同步版本

文件追加操作

3、文件追加

使用fs.appendFile(file, data[, options], callback)方法向file写入数据。若文件不存在则自动创建。data参数为字符串或Buffer,options为可选参数(对象或字符串),包含以下属性:

  • encoding:默认值为'utf8',指定编码格式。
  • mode:默认值为0o666,指定文件打开权限模式。
  • flag:默认值为'a',指定文件打开标志。

具体使用示例如下:


fs.appendFile('./test.txt','hello world!\r\n',(err)=>{
  if(err) throw err;
  console.log('写入成功');
});
//appendFile同步版本,返回值为undefined
fs.appendFileSync('./test.txt','hello nodejs!\r\n');

文件读取与写入

4、文件读取和写入

文件读取使用fs.readFile(file[, options], callback)方法,各参数含义如下:

  • file:文件名或文件描述符。
  • options:对象或字符串。若为对象,包含encoding(默认null)和flag(默认'r')。
  • callback:回调函数,参数为(err, data)。

若指定文件不存在,将直接抛出错误。具体使用示例如下:


fs.readFile('./test4.txt',{encoding:'utf8',flag:'r'},(err,data)=>{
if(err) throw err;
console.log(data);
});
var data = fs.readFileSync('../test4.txt',{encoding:'utf8',flag:'r'});

文件写入数据使用fs.writeFile(file, data[, options], callback)方法,各参数含义如下:

  • file:文件名或文件描述符。
  • data:字符串或Buffer对象。
  • options:对象或字符串。若为对象,包含encoding(默认'utf8')、mode(默认0o666)和flag(默认'w')。
  • callback:回调函数,参数为err。

若文件不存在则创建新文件;若存在则覆盖原文件内容。具体使用示例如下:


var data = "hello node!";
fs.writeFile('./test1.txt',data,{flag:'w'},(err)=>{
if(err) throw err;
console.log('written ok.');
});
fs.writeFileSync('./test1.txt',data,{flag:'w'});

此外,也可以利用fs的open、read、write、stat等方法组合实现文件的读取与写入操作。

fs.open(path, flags[, mode], callback)方法用于打开文件并获取文件句柄,flags参数支持以下值:

  • 'r':以只读方式打开文件,若文件不存在则报错。
  • 'r+':以读写方式打开文件,若文件不存在则报错。
  • 'rs+':在同步模式下,以读写方式打开文件。
  • 'w':以写方式打开文件,若文件不存在则创建。
  • 'wx':以写方式打开文件,若文件不存在则抛出异常。
  • 'w+':以读写方式打开文件,若文件不存在则创建;若存在则清空文件内容。
  • 'wx+':以读写方式打开文件,若文件不存在则抛出异常。
  • 'a':以追加方式打开文件,若文件不存在则创建。
  • 'ax':以追加方式打开文件,若文件不存在则抛出异常。
  • 'a+':以追加和读方式打开文件,若文件不存在则创建。
  • 'ax+':以追加和读方式打开文件,若文件不存在则失败。

回调函数包含(err, fd)两个参数。

fs.read(fd, buffer, offset, length, position, callback)方法用于从文件中读取数据并存入Buffer,各参数含义如下:

  • buffer:Buffer对象,用于存储读取的数据。
  • offset:Buffer中开始写入的位置。
  • length:需要读取的字节长度。
  • position:指定从文件的哪个位置开始读取;若设置为null,则从文件当前位置开始读取。
  • callback:包含三个参数(err, bytesRead, buffer),其中bytesRead为实际读取的字节数。
  • fs.write(fd, buffer, offset, length[, position], callback)方法用于将Buffer数据写入指定文件,各参数含义如下:
  • offset和length指定Buffer中参与写入的部分。
  • position:指定文件中的开始写入位置;若不为数字,则从文件当前位置开始写入。

下面是一个使用open、write、read、stat方法实现文件内容复制的函数示例:


function copy(src, dest) {
const destFd = fs.openSync(dest, 'w+'),
   srcStat = fs.statSync(src);
const buffer = new Buffer(srcStat.size);
console.log('复制开始...');
console.log(src+'大小:'+srcStat.size)
fs.open(src,'r',(err,fd)=>{
  if(err) throw err;
  fs.read(fd,buffer,0,srcStat.size,null,(err,bytesRead,buff)=>{
    if(err) throw err;
    console.log('实际读取大小:'+bytesRead);
    fs.close(fd,()=>{});
    fs.write(destFd,buff,0,bytesRead,null,(err, written, buffer)=>{
      if(err) throw err;
      console.log('已完成复制,向'+dest+'写入了'+written);
      fs.close(destFd,()=>{});
    });
  });
});
}
copy('./app.js','./appbak.js');

执行结果如下:

E:\\developmentdocument\\nodejsdemo>node fs-examples.js 复制开始... ./app.js大小:1094 实际读取大小:1094 已完成复制,向./appbak.js写入了1094

文件重命名与删除

5、文件重命名、删除

方法fs.rename(oldPath, newPath, callback)可实现文件重命名或移动。若oldPath与newPath位于同一目录,则为重命名;否则为移动并重命名。具体使用如下:


fs.rename('../test4.txt','./test4.txt',(err)=>{
  if(err) throw err;
  console.log('rename success.');
});
fs.renameSync('../test2.txt','../test4.txt');

文件删除需使用fs.unlink(path, callback)方法,用法简单,示例如下:


fs.unlink('./dir/11.txt',(err)=>{
  if(err) throw err;
  console.log('delete file success.');
});
fs.unlinkSync('./dir/11.txt');

目录创建、扫描与删除

6、创建、读取、删除目录

创建目录使用fs.mkdir(path[, mode], callback)方法,mode参数默认为0o777。但该方法仅能创建一级目录,否则抛出异常,示例如下:


fs.mkdir('./a',0o777,(err)=>{
  if(err) throw err;
  console.log('mkdir success');
});
//mkdir的同步版本,返回值为undefined
fs.mkdirSync('./test',0o777);

为实现多级目录创建,可结合path模块的dirname方法自定义函数,示例如下:


function isFileExists(filePath){
  var bool = !0;
  try{
    fs.accessSync(filePath,fs.F_OK);
  }catch(err){
    bool = !1;
  }
  return bool;
}
function mkdirp(dirpath,mode,cb){
  if(isFileExists(dirpath)){
    cb(dirpath);
  }else{
    mkdirp(path.dirname(dirpath),mode,function(){
      fs.mkdir(dirpath,mode,cb);
    });
  }
}

扫描目录需使用fs.readdir(path[, options], callback)方法,options参数为字符串或对象,回调函数包含(err, files)两个参数,files为文件名数组。该方法同样仅支持扫描一级目录,示例如下:


fs.readdir('./',(err,files)=>{
  if(err) throw err;
  console.log(files);
});

若需实现递归扫描目录,可自定义函数,示例如下:


function scandir(dirpath){
  var filesArr = {};
  if(!isFileExists(dirpath)) return !1;
  function scan(filepath){
    var statObj = fs.statSync(filepath);
    if(!statObj.isDirectory()) return filesArr.push(filepath);
    var files = fs.readdirSync(filepath);
    files.forEach((file,idx,arr)=>{
      scan(filepath+'/'+file);
    });
  }
  scan(dirpath);
  return filesArr;
}

删除目录使用fs.rmdir(path, callback)方法,仅能删除一级目录且目录必须为空,示例如下:


fs.rmdir('./dir',(err)=>{
  if(err) throw err;
  console.log('delete dir success.');
});

若要实现类似rm -rf的递归删除效果,可使用如下代码:


function deldirs(dirpath){
  var stat = null,
    emptyFoldersArr = [];
  
  function scan(spath){
    var files = fs.readdirSync(spath);
    emptyFoldersArr.push(spath);
    if(files.length>0){
      files.forEach((file,idx,arr)=>{
        if(fs.statSync(spath+'/'+file).isDirectory()){
          scan(spath+'/'+file);
        }else{
          return fs.unlinkSync(spath+'/'+file),!0;
        }
      });
    }
  }
  scan(dirpath);
  for(var l=emptyFoldersArr.length-1,i=l;i>=0;i--){
    fs.rmdirSync(emptyFoldersArr[i]);
  }
}

获取绝对路径

7、获取路径的绝对路径

使用fs.realpath(path[, options], callback)方法可获取path的绝对路径,回调函数包含(err, resolvedPath)两个参数,示例如下:


fs.realpath('./test.txt',(err,resolvePath)=>{
  if(err) throw err;
  console.log(resolvePath);
});
console.log(fs.realpathSync('./test.txt'));

执行结果如下所示:

E:\\developmentdocument\\nodejsdemo>node fs-examples.js E:\\developmentdocument\\nodejsdemo\\test.txt

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。

作者最新文章