Node-fs模块

一.内置fs模块


fs模块的基本作用是进行文件的读写,表示文件系统,为什么需要文件的读写,举个例子我们在客户端看到的图片,那么它是怎么来的? 其实基本步骤就是:

  1. Node通过fs模块从服务器上进行文件的读取。
  2. 将图片从服务器硬盘中读取到Node程序中。
  3. 通过网络返回给客户端,客户端进行展示图片。

对于任何一个为服务端服务的语言或者框架来说通常都有自己的文件系统,原因如下:

  • 因为服务器需要将各种数据,文件存放在不同的地方。
  • 用户的数据大多数是存放在数据库中的。
  • 某些配置文件或者用户资源都是以文件的形式存放在操作系统上的。

Node也有自己的文件系统操作模块,就是fs 借助于Node帮我们封装的文件系统,我们可以在任何的操作系统上面直接去操作文件,这也是Node可以开发服务器的一大原因,也是它可以成为前端自动化脚本等热门工具的原因。

二.fs的API介绍


Node文件系统的API是非常多的,但是一般仅仅分为三类 - Node-fs API

  • 方式一:同步操作文件:代码会被阻塞,不会继续执行;
  • 方式二:异步回调函数操作文件:代码不会被阻塞,需要传入回调函数,当获取到结果时,回调函数被执行;
  • 方式三:异步Promise操作文件:代码不会被阻塞,通过fs.promises调用方法操作,会返回一个Promise,可以通过then,catch进行处理;
js 复制代码
const fs = require("fs");

// 1.同步读取
const res1 = fs.readFileSync("./aaa.txt");
console.log(res1, "以二进制读取出来,以16进制展示");

// 2.异步读取
fs.readFile("./aaa.txt", { encoding: "utf-8" }, (err, data) => {
  if (err) {
    console.log("读取错误");
    return;
  }
  console.log(data, "读取的文件信息为~");
});

// 3.Promise读取
fs.promises.readFile("./aaa.txt",{encoding:"utf-8"}).then((res)=>{
    console.log(res);
}).catch(err=>{
    console.log(err);
})

三.文件描述符


文件描述符:在常见的操作系统中,对于每个进程,内核都维护着一张打开着的文件和资源的表格,每个打开的文件都分配了一个成为文件描述符的简单的数字标识符,在系统层,所有的文件系统都使用这些文件描述符来标识和跟踪每个特定的文件 ,Windows 系统使用了一个虽然不同但概念上类似的机制来跟踪资源,为了简化用户的工作,Node.js 抽象出操作系统之间的特定差异,并为所有打开的文件分配一个数字型的文件描述符。

当我们打开一个文件,系统就会给我们分配一个文件描述符。

js 复制代码
const fs = require("fs");

// 打开文件,让系统分配文件描述符
fs.open('./aaa.txt',(err,fd)=>{
    if(err){
        console.log("打开文件错误");
        return 
    }
    console.log(fd);
    // 读取文件的信息
    fs.fstat(fd,(err,status)=>{
        if(err){
            console.log("获取文件描述符错误");
            return
        }
        console.log(status);
        // 关闭这个文件
        fs.close(fd);
    })
})

四.文件的写入


如果我们想要对文件进行写入的时候我们可以使用如下API在文件中写入内容;

js 复制代码
fs.writeFile(file, data[, options], callback):
js 复制代码
const fs = require("fs");
// 定义一段内容
const content = "HelloWorld,myName is nice";
// 进行文件的写入
fs.writeFile(
  "./ccc.txt",
  content,
  {
    flag: "a+",
    encoding: "utf-8",
  },
  (err) => {
    if (err) {
      console.log("文件写入失败");
    } else {
      console.log("文件写入成功!");
    }
  },
);

五.文件flag选项


在我们文件进行读写的时候可以通过flag对当前我们操作的文件进行控制,但是要注意它和操作系统对文件管控权限的区别。

对比项 Node.js 文件 flag 操作系统文件权限
属于谁? Node.js 代码层 操作系统内核
作用 规定怎么打开文件 规定能不能操作文件
控制范围 读 / 写 / 追加 / 创建 / 覆盖 读 / 写 / 执行 / 归属用户 / 组
优先级 低 高(权限不足直接报错)
生命周期 仅当前打开文件有效 永久存在,直到被 chmod 修改
例子 w清空写入 0o444只读无法写入

常见的flag的值有:

  • w 打开文件写入,默认值;
  • w+ 打开文件进行读写(可读可写),如果不存在则创建文件;
  • r 打开文件读取,读取时的默认值(亲测:如果放在写入中用会写入失败);
  • r+ 打开文件进行读写,如果不存在那么抛出异常;
  • a 打开要写入的文件,将流放在文件末尾。如果不存在则创建文件;
  • a+ 打开文件以进行读写(可读可写),将流放在文件末尾。如果不存在则创建文件

六.encoding选项


www.jianshu.com/p/899e749be...

在文件读取的时候如果不写encoding返回的结果是Buffer。

js 复制代码
const fs = require("fs");
fs.readFile("./aaa.txt",(err,data)=>{
    if(err) return
    console.log(data);
})
// <Buffer 48 65 6c 6c 6f 20 57 6f 72 6c 64 0d 0a e4 bd a0 e5 a5 bd e6 9d 8e e9 93 b6 e6 b2 b3 ef bc 81>

七.文件夹操作


fs除了能够进行文件的操作也能进行文件夹的操作。

js 复制代码
const fs = require("fs");
// 创建文件夹
fs.mkdir('./why',(err)=>{
    console.log(err);
})

读取文件夹中的信息

js 复制代码
const fs= require("fs");
// 读取文件夹
fs.readdir('./why',(err,files)=>{
    console.log(files);
})

// 读取文件夹获取文件夹中文件的信息
fs.readdir('./why',{withFileTypes:true},(err,files)=>{
    console.log(files);
})

如果type类型为1则表示文件,如果值为2表示文件夹,可以使用isDirectory()这个方法来进行判断

js 复制代码
// 读取文件夹获取文件夹中文件的信息,没有withFileTypes就会不能用isDirectory
fs.readdir('./why',{withFileTypes:true},(err,files)=>{
    console.log(files);
    files.forEach(item=>{
        if(item.isDirectory()){
            fs.readdir(`./why/${item.name}`,{withFileTypes:true},(err,files)=>{
                console.log(files);
            })
        }else{
            console.log("item是一个文件",item.name);
        }
    })
})

案例:递归读取文件夹获取文件夹中文件的信息

js 复制代码
// 递归读取文件夹中的文件
function readFileLoop(path) {
  fs.readdir(path, { withFileTypes: true }, (err, files) => {
    files.forEach((item) => {
      if (item.isDirectory()) {
        readFileLoop(`${path}/${item.name}`);
      }else{
        console.log("读取的文件为:",item);
      }
    });
  });
}

readFileLoop("./why");

八.文件夹和文件重命名


fs模块中也有对文件和文件夹更改名称的API

js 复制代码
// 对文件夹进行重命名
fs.rename('./why','./whynew',(err)=>{
    console.log("重命名结果",err);
})

// 对文件进行重命名
fs.rename('./aaa.txt','666.txt',(err)=>{
    console.log("文件重命名结果",err);
})
相关推荐
星核0penstarry24 分钟前
企业 API 向后兼容实战:版本控制、废弃字段通知与灰度发布策略
人工智能·后端·api·接口隔离原则·版本控制·架构设计·后端架构
用户别睡觉1 小时前
自己搭的中文 PDF RAG 接了 Redis 缓存、跑了 RAGAS,以为能写“提速多少、准确率多少”,结果两个都没按预期来。
后端
彭亚川Allen1 小时前
985 在职研究生到底怎么样?是不是水硕?是不是.....?
前端·后端·程序员
乘风2481 小时前
# 我做了个会遗忘的 AI 记忆,召回率反而从 8% 涨到 100%
后端
Rain的Java大神之路1 小时前
面试被LeetCode 27(移除元素)问懵?别再用两层 for 循环了:一道“简单题”吃透双指针原地删除,附面试加分话术 + 11 个避坑清单
后端·leetcode·面试
利威尔xu2 小时前
Go IM 源码实战(11):token 只是个 HASH,多端互踢的顺序错了就踢错人
后端·微服务·面试·架构·golang
猿究院--Cu-Sn合金2 小时前
Spring Boot + DeepSeek 求职 Agent 实践:工具注册、多轮调用与简历 JD 对比
数据库·人工智能·spring boot·后端·deepseek
程序员cxuan2 小时前
别学 subagent 了,很可能要凉了。
后端·agent·ai编程
小咕聊编程2 小时前
基于Django的个人摄影博客网站设计与开发
后端·python·django
未秃头的程序猿3 小时前
@ConditionalOnMissingBean 把我配好的 RabbitMQ 手动 ack 吃掉了
后端·rabbitmq