浅谈Node.js:fs文件系统模块


Posted in Javascript onDecember 08, 2016

fs文件系统模块,这是一个非常重要的模块,对文件的操作都基于它。该模块的所有方法都有同步和异步两种方式,下面便介绍一下该模块的使用。

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

使用fs.access(path[, mode], callback)方法检查权限,mode参数是一个整数,有以下常量值:

  • fs.constants.F_OK     path对调用进程是可见的,既存在
  • fs.constants.R_OK     path是可读的
  • fs.constants.W_OK    path是可写的
  • fs.constants.X_OK     path是可执行的

 使用如下所示:

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

同步版本,如果发生异常,则直接抛出异常,否则什么也不做。同步版本可以利用try..catch来做,适用所有方法,如下所示:

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

2、获取文件状态

使用fs.stat(path, callback)fs.statSync(path)方法来获取指定path的状性,callback有(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.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写入数据,如果file不存在,则创建file,data参数为字符串或buffer,options可选参数是对象或字符串,具有以下属性:

  • encoding  |  default = 'utf8' 编码
  • mode  default = 0o666 打开模式
  • flag  default = '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和flag,前者默认为null,后者为'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、mode以及flag,依次默认为utf8,0o666,'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+' - 以追加和读方式打开文件,若文件不存则失败

callback回调函数有(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参数为字符串或对象,callback回调函数有(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的绝对路径,callback有(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

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

Javascript 相关文章推荐
jquery绑定原理 简单解析与实现代码分享
Sep 06 Javascript
DOM2非标准但却支持很好的几个属性小结
Jan 21 Javascript
JavaScript基本编码模式小结
May 23 Javascript
JQuery制作的放大效果的popup对话框(未添加任何jquery plugin)分享
Apr 28 Javascript
JQuery记住用户名和密码的具体实现
Apr 04 Javascript
sliderToggle在写jquery的计时器setTimeouter中不生效
May 26 Javascript
原生js制作简单的数字键盘
Apr 24 Javascript
JavaScript中使用concat()方法拼接字符串的教程
Jun 06 Javascript
使用CoffeeScrip优美方式编写javascript代码
Oct 28 Javascript
Vue中之nextTick函数源码分析详解
Oct 17 Javascript
JavaScript常见JSON操作实例分析
Aug 08 Javascript
微信小程序拍照和摄像功能实现方法示例
Feb 01 Javascript
Bootstrap基本插件学习笔记之模态对话框(16)
Dec 08 #Javascript
概述BootStrap中role="form"及role作用角色
Dec 08 #Javascript
Bootstrap基本插件学习笔记之标签切换(17)
Dec 08 #Javascript
Bootstrap基本插件学习笔记之Popover提示框(19)
Dec 08 #Javascript
JS焦点图,JS 多个页面放多个焦点图的实例
Dec 08 #Javascript
BootStrap 图标icon符号图标glyphicons不正常显示的快速解决办法
Dec 08 #Javascript
Bootstrap基本插件学习笔记之Tooltip提示工具(18)
Dec 08 #Javascript
You might like
php数组索引的Key加引号和不加引号的区别
2014/08/19 PHP
php在linux下检测mysql同步状态的方法
2015/01/15 PHP
PHP文件上传类实例详解
2016/04/08 PHP
Asp.net下利用Jquery Ajax实现用户注册检测(验证用户名是否存)
2010/09/12 Javascript
文本框水印提示效果的简单实现代码
2014/02/22 Javascript
jQuery简易图片放大特效示例代码
2014/06/09 Javascript
Javascript 运动中Offset的bug解决方案
2014/12/24 Javascript
给before和after伪元素设置js效果的方法
2015/12/04 Javascript
JS实现刷新父页面不弹出提示框的方法
2016/06/22 Javascript
谈谈PHP中相对路径的问题与绝对路径的使用
2016/08/16 Javascript
谈谈对vue响应式数据更新的误解
2017/08/01 Javascript
jquery实现左右轮播图效果
2017/09/28 jQuery
vue中 数字相加为字串转化为数值的例子
2019/11/07 Javascript
Vue 实现可视化拖拽页面编辑器
2021/02/01 Vue.js
[00:08]DOTA2勇士令状等级奖励“天外飞星”
2019/05/24 DOTA
Python中线程的MQ消息队列实现以及消息队列的优点解析
2016/06/29 Python
Python实现遍历目录的方法【测试可用】
2017/03/22 Python
python实现比较类的两个instance(对象)是否相等的方法分析
2019/06/26 Python
Python创建一个元素都为0的列表实例
2019/11/28 Python
Python Lambda函数使用总结详解
2019/12/11 Python
基于Python组装jmx并调用JMeter实现压力测试
2020/11/03 Python
Python eval函数介绍及用法
2020/11/09 Python
用python监控服务器的cpu,磁盘空间,内存,超过邮件报警
2021/01/29 Python
css3实现背景图片拉伸效果像桌面壁纸一样
2013/08/19 HTML / CSS
Beach Bunny Swimwear官网:设计师泳装和性感比基尼
2019/03/13 全球购物
Bluebella法国官网:英国性感内衣品牌
2019/05/03 全球购物
LN-CC日本:高端男装和女装的奢侈时尚目的地
2019/09/01 全球购物
《学会待客》教学反思
2014/02/22 职场文书
幼儿园教师自我鉴定
2014/03/20 职场文书
个人作风建设心得体会
2014/10/22 职场文书
2015年大学生村官工作总结
2015/04/21 职场文书
观看安全警示教育片心得体会
2016/01/15 职场文书
初中物理教学反思
2016/02/19 职场文书
Python中OpenCV实现简单车牌字符切割
2021/06/11 Python
Python编程编写完善的命令行工具
2021/09/15 Python
基于Python编写一个监控CPU的应用系统
2022/06/25 Python