nodejs fs模块

本文详细介绍了Node.js的FileSystem模块,包括读文件、写文件、目录操作和文件监视等功能。讨论了各种文件操作模式,如读取、写入、追加等,并提供了fs模块相关函数的使用示例,如fs.readFile、fs.writeFile、fs.mkdir等。同时,还提到了流的操作和文件监视,帮助读者深入理解Node.js中的文件系统操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

nodejs FileSystem 模块

nodejs 的文件模块 从读写两方面入手。

首先说明一下文件操作模式
‘r’ - 以读取模式打开文件。如果文件不存在则发生异常。
‘r+’ - 以读写模式打开文件。如果文件不存在则发生异常。
‘rs+’ - 以同步读写模式打开文件。命令操作系统绕过本地文件系统缓存。
这对 NFS 挂载模式下打开文件很有用,因为它可以让你跳过潜在的旧本地缓存。 它对 I/O 的性能有明显的影响,所以除非需要,否则不要使用此标志。
注意,这不会使 fs.open() 进入同步阻塞调用。 如果那是你想要的,则应该使用 fs.openSync()。
‘w’ - 以写入模式打开文件。文件会被创建(如果文件不存在)或截断(如果文件存在)。
‘wx’ - 类似 ‘w’,但如果 path 存在,则失败。
‘w+’ - 以读写模式打开文件。文件会被创建(如果文件不存在)或截断(如果文件存在)。
‘wx+’ - 类似 ‘w+’,但如果 path 存在,则失败。
‘a’ - 以追加模式打开文件。如果文件不存在,则会被创建。
‘ax’ - 类似于 ‘a’,但如果 path 存在,则失败。
‘a+’ - 以读取和追加模式打开文件。如果文件不存在,则会被创建。
‘ax+’ - 类似于 ‘a+’,但如果 path 存在,则失败

调用 fs模块

var fs = require("fs");

读文件

  1. readFile 读取文件函数
    该函数是异步读取文件内容
/**
 * 参数: filename , [options] , callback
 * filename: 必选参数,一定是文件的具体路径
 * [options]: 可选参数 两种凡方式 第一种 不使用flag 则直接"utf8" ,否则格式如下
 * callback : 读取文件的回调函数 第一个默认是err , 只有两个参数的时候才会将内容显示出来(data 参数可选)
 */

fs.readFile(__dirname+'/log.txt',{flag:"r",encoding:"utf8"},function (err,data) {
    //如果读取文件出错 则 err = true
    if(err){
        console.log("读取文件出错!");
        console.error(err);
    }else{
        console.log("读取文件成功");
        console.log(data);
    }
})

readFile同步调用函数为readFileSync(filename,[options]),该函数直接返回 file内容(buffer),如果指定了options编码格式 则返回的内容是字符串。
2. 读取打开的文件 fs.open /fs.read

windows下文字描述符如下:
O_RDONLY: 0,
O_WRONLY: 1,
O_RDWR: 2,
S_IFMT: 61440,
S_IFREG: 32768,
S_IFDIR: 16384,
S_IFCHR: 8192,
S_IFLNK: 40960,
O_CREAT: 256,
O_EXCL: 1024,
O_TRUNC: 512,
O_APPEND: 8,
F_OK: 0,
R_OK: 4,
W_OK: 2,
X_OK: 1

fs.open(filename,flags,[mode],callback)

/**
 * 先打开文件 然后再读取 open read 函数
 * open(filename,flags,[mode],callback)
 * filename:完整的文件名(必选参数)
 * flags: 操作标识 r:以读方式打开,r+:以读写模式打开文件
 * [modes],权限,777 表示任何用户读写可以执行 默认是0666 (只有文件已经存在才有效)
 * callback 打开文件之后回调函数 有两个参数 第一个默认err, 第二个为整数 表示打开文件返回的文字描述符
 *
 *
 */

fs.open(__dirname+'/log.txt',"r","0666",function (err,fd) {
    if(err){
        console.error(err);
    }else{
        console.log(fd);
        console.log(fs.constants); //得到所有的文字描述符
    }
});

fs.read
函数参数
fs.read(fd,buffer,offset,length,position,callback);

/**
 * fs.read(fd,buffer,offset,length,position,callback);
 * fd:fs.open()返回的文件描述符
 * buffer:数据将被分配的对象区域 ,由v8引擎分配的内存
 * offset:向buffer开始写入的偏移量 以字节为单位 (buffer内存开始的位置)
 * length:指定要读取的文件长度
 * position:指定从文件中哪个位置开始读取文件 , 默认是从文件其实位置开始。 (读取文件开始的位置)
 * callback:回调函数 (err,bytesRead,buffer) bytesRead 表示实际读取的字节数 buffer 表示被读取的对象
 */

fs.open(__dirname+"/log.txt","r","0666",function (err,fd) {
    if(err){
        console.error(err);
    }else{
        var buffer = new Buffer(255);
        console.log(buffer.length);
        //每个汉字的utf8编码是3个字节,英文的utf8编码是1个 下面的9 相当于只读取了3个汉字
        fs.read(fd,buffer,0,9,0,function (err,bytesRead,buffer) {
            if(err){
                console.error(err);
            }else{
                console.log(bytesRead);
                console.log(buffer.slice(0,bytesRead).toString());
                fs.read(fd,buffer,0,9,null,function (err,bytesRead,buffer) {
                    console.log(bytesRead);
                    console.log(buffer.slice(0,bytesRead).toString());
                })
            }
        })
    }
});

写文件

  1. fs.writeFile
    参数:fs.writeFile(filename,data,[options],callback)
/**
 * filename:完整文件路径 如果文件已存在则替换文件内容 ,若文件不存在则创建一个同名文件并追加内容
 * data:anything,在这里我使用的是buffer  如果 data 是一个 buffer,则忽略 encoding 选项。它默认为 'utf8'
 * [options]:文件操作类型 读写 同步等等 还有文件的编码等
 * callback:只err
 */
fs.writeFile(__dirname+'/write.txt',wbuffer,{encoding:"utf8",flag:"w"},(err)=>{
    if(err){
        console.error(err);
    }else{
        console.log("write success ");
    }
})

//追加文件
fs.appendFile(__dirname+'/write.txt',wbuffer,{encoding:"utf8",flag:"a+"},(err)=>{
    if(err){
        console.error(err);
    }else{
        console.log("追加成功");
    }
})
  1. fs.write()
    参数fs.write(fd, buffer, offset, length, position, callback);

fs.open(__dirname+'/write.txt',"a+",(err,fd)=>{
    if(err) {
        console.error(err);
    }else{
        console.log("打开成功!");
        fs.write(fd,wbuffer,0,12,0,(err,bytesWritten,buffer)=>{
            if(err){
                console.error(err);
            }else{
                console.log("写入成功");
                console.log(bytesWritten); // 12
                console.log(buffer.slice(0,bytesWritten).toString()); //写入文本

                //刷新缓存区 fs.write写入文件时,操作系统是将数据读到内存,再将数据写到文件中,
                //当数据读完并不代表数据已经写完,因为有一部分还可能在内存中的缓冲区中
                //我们可以使用fs.fsync方法将内存中的数据写入文件  刷新内存缓冲区
                fs.fsync(fd,(err)=>{ //可能不会执行
                    if(err){
                        console.error(err);
                    }else{
                        console.log("flush success");
                    }
                });
                fs.close(fd,(err)=>{if(err){console.error(err)}});
            }
        })
    }
});

目录

  1. 创建目录

    fs.mkdir(path,[mode],callback);

 /**
 * path:被创建的目录名  完整目录路径
 * [mode]:创建的目录权限 默认是 777 可读可写
 * callback
 */
fs.mkdir(__dirname+'/fsDir',777,(err)=>{
   if(err){
       console.error(err);
   }else{
       console.log("创建目录成功");
   }
}); 
  1. 读取目录
    fs.readdir(path,options,callback)
    fs.stat() 用于检查一个文件是否存在 ,返回的 stat是 fs.Stat一个对象实例,提供如:isFile, isDirectory,isBlockDevice等方法及size,ctime,mtime等属性
/**
 * 
 * path:目录路径
 * options: encoding 默认utf8
 * callback : err , files:返回该目录下所有的文件包括文件夹 但是不包括以.. . 开头的文件
 */
var path = require('path');
fs.readdir(__dirname+'/fsDir/',(err,files)=>{
    if(err){
        console.error(err);
    }else{
        console.log("读取目录成功");
        files.forEach(function (file) {

           console.log(__dirname+"/fsDir/"+file); // D:\git\node_demo/fsDir/123
           //得到文件的路径 使用path.mormalize()规范化路径的分隔符
           var filePath = path.normalize(__dirname+"/fsDir/"+file);//D:\git\node_demo\fsDir\123is:dir
           //fs.stat() 检查一个文件是否存在      //fs.access
           // stats:
           fs.stat(filePath,function (err,stats) {
              //stats确定
               if(stats.isFile()){
                   console.log(filePath+'is:file');
               }
               if(stats.isDirectory()){
                   console.log(filePath+'is:dir');
               }
           });
        });
    }
});
  1. 目录是否存在
    fs.exist(path,callback);
//exists=true/false
fs.exists(__dirname+'/fsDir',function (exists) {
   if(exists){
       console.log("目录存在");
   }else{
       console.log("目录不存在");
   }
});

监视

  • 文件监视
    监视文件是否被修改
    fs.watchFile(filename,[options],listener);
/**
 * fs.watchFile(filename,[options],listener)
 * filename:文件名 完整路径
 * options: 可省略 如果不省略就应该是一个对象{},这个对象包含两个属性:
 *    persistent:表示当文件正再被监视时,进程是否应该继续运行
 *    interval: 表示指定文件夹应该每隔多少毫秒被轮询一次
 *    默认值:persistent:true,interval:5007;
 *listener:类型为function 指定文件发生变化时回调 有两个参数
 *    curr:fs.Stat 对象 表示修改后对象
 *    prev: fs.Stat 对象 表示修改前对象
 */
fs.watchFile(__dirname+'/fsDir/123.txt',{persistent:true,interval:2000},(curr, prev)=>{
    if(Date.parse(prev.ctime) === 0){
        console.log("文件被创建");
    }else if(Date.parse(curr.ctime) ===0){
        console.log("文件被删除")
    }else if(Date.parse(curr.mtime) != Date.parse(prev.mtime)) {
        console.log('文件有修改');
    }
});
fs.watchFile(__dirname + '/fsDir/123.txt',{persistent:true,interval:2000},function (curr, prev) {
    console.log("文件有修改");
})

取消监视文件

//取消对文件进行监视
//fs.unwatchFile(filename, [listener]);

/**
 * filename, 完整路径及文件名;
 * [listener], 要取消的监听器事件,如果不指定,则取消所有监听处理事件
 */

var listener = function (curr, prev) {
  console.log('取消监视函数')
}
fs.unwatchFile(__dirname + '/fsDir/123.txt', listener);

流的操作

  • 创建读取流
//fs.createReadStream(path, [options])
/**
 * path 文件路径
 * [options] flags:指定文件操作,默认'r',读操作;encoding,指定读取流编码;autoClose, 是否读取完成后自动关闭,默认true;start指定文件开始读取位置;end指定文件开始读结束位置
 */

var rs = fs.createReadStream(__dirname + '/test.txt', {start: 0, end: 2});
  //open是ReadStream对象中表示文件打开时事件,
rs.on('open', function (fd) {
  console.log('开始读取文件');
});

rs.on('data', function (data) {
  console.log(data.toString());
});

rs.on('end', function () {
  console.log('读取文件结束')
});
rs.on('close', function () {
  console.log('文件关闭');
});

rs.on('error', function (err) {
  console.error(err);
});

//暂停和回复文件读取;
rs.on('open', function () {
  console.log('开始读取文件');
});

rs.pause();

rs.on('data', function (data) {
  console.log(data.toString());
});

setTimeout(function () {
  rs.resume();
}, 2000);
  • 创建写入流
//fs.createWriteStream(path, [options])
/**
 * path 文件路径
 * [options] flags:指定文件操作,默认'w',;encoding,指定读取流编码;start指定写入文件的位置
 */

/* ws.write(chunk, [encoding], [callback]);
 * chunk,  可以为Buffer对象或一个字符串,要写入的数据
 * [encoding],  编码
 * [callback],  写入后回调
 */

/* ws.end([chunk], [encoding], [callback]);
 * [chunk],  要写入的数据
 * [encoding],  编码
 * [callback],  写入后回调
 */

var ws = fs.createWriteStream(__dirname + '/test.txt', {start: 0});
var buffer = new Buffer('我也喜欢你');
ws.write(buffer, 'utf8', function (err, buffer) {
  console.log(arguments);
  console.log('写入完成,回调函数没有参数')
});
//最后再写入的内容
ws.end('再见');
//使用流完成复制文件操作
var rs = fs.createReadStream(__dirname + '/test.txt')
var ws = fs.createWriteStream(__dirname + '/test/test.txt');

rs.on('data', function (data) {
  ws.write(data)
});

ws.on('open', function (fd) {
  console.log('要写入的数据文件已经打开,文件描述符是: ' + fd);
});

rs.on('end', function () {
  console.log('文件读取完成');
  ws.end('完成', function () {
    console.log('文件全部写入完成')
  });
});


//关于WriteStream对象的write方法返回一个布尔类型,当缓存区中数据全部写满时,返回false;
//表示缓存区写满,并将立即输出到目标对象中

//第一个例子
var ws = fs.createWriteStream(__dirname + '/test/test.txt');
for (var i = 0; i < 10000; i++) {
  var w_flag = ws.write(i.toString());
  //当缓存区写满时,输出false
  console.log(w_flag);
}


//第二个例子
var ws = fs.createWriteStream(__dirname + '/test/untiyou.mp3');
var rs = fs.createReadStream(__dirname + '/test/Until You.mp3');
rs.on('data', function (data) {
  var flag = ws.write(data);
  console.log(flag);
});

//系统缓存区数据已经全部输出触发drain事件
ws.on('drain', function () {
  console.log('系统缓存区数据已经全部输出。')
});
  • 管道pipe实现流读写
//rs.pipe(destination, [options]);
/**
 * destination 必须一个可写入流数据对象
 * [opations] end 默认为true,表示读取完成立即关闭文件;
 */

var rs = fs.createReadStream(__dirname + '/test/Until You.mp3');
var ws = fs.createWriteStream(__dirname + '/test/untiyou.mp3');
rs.pipe(ws);
rs.on('data', function (data) {
  console.log('数据可读')
});
rs.on('end', function () {
  console.log('文件读取完成');
  //ws.end('再见')
});

最后 本文是参见 明明三省的博客,简述了自己觉得重要的部分。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值