Nodejs 第二十章(fs 上)

概述

在 Node.js 中,fs 模块是文件系统模块(File System module)的缩写,它提供了与文件系统进行交互的各种功能。通过 fs 模块,你可以执行诸如读取文件、写入文件、更改文件权限、创建目录等操作,Node.js 核心API之一

fs多种策略

js 复制代码
import fs from 'node:fs'
import fs2 from 'node:fs/promises'
//读取文件
fs2.readFile('./index.txt').then(result => {
    console.log(result.toString())
})
fs.readFile('./index.txt', (err, data) => {
    if (err) {
        return err
    }
    console.log(data.toString())
})
let txt = fs.readFileSync('./index.txt')
console.log(txt.toString())
  1. fs支持同步和异步两种模式 增加了Sync fs 就会采用同步的方式运行代码,会阻塞下面的代码,不加Sync就是异步的模式不会阻塞。

  2. fs新增了promise版本,只需要在引入包后面增加/promise即可,fs便可支持promise回调。

  3. fs返回的是一个buffer二进制数据 每两个十六进制数字表示一个字节

js 复制代码
<Buffer 31 e3 80 81 e9 82 a3 e4 b8 80 e5 b9 b4 e5 86 b3 e8 b5 9b ef bc 8c e6 98 af 53 53 47 e5 af b9 e6 88 98 53 4b 54 ef bc 8c e6 9c 80 e7 bb 88 e6 af 94 e5 ... 635 more bytes>

常用API 介绍

读取文件 readFile 读一个参数 读取的路径, 第二个参数是个配置项

encoding 支持各种编码 utf-8之类的

flag 就很多了

  • 'a': 打开文件进行追加。 如果文件不存在,则创建该文件。

  • 'ax': 类似于 'a' 但如果路径存在则失败。

  • 'a+': 打开文件进行读取和追加。 如果文件不存在,则创建该文件。

  • 'ax+': 类似于 'a+' 但如果路径存在则失败。

  • 'as': 以同步模式打开文件进行追加。 如果文件不存在,则创建该文件。

  • 'as+': 以同步模式打开文件进行读取和追加。 如果文件不存在,则创建该文件。

  • 'r': 打开文件进行读取。 如果文件不存在,则会发生异常。

  • 'r+': 打开文件进行读写。 如果文件不存在,则会发生异常。

  • 'rs+': 以同步模式打开文件进行读写。 指示操作系统绕过本地文件系统缓存。

    这主要用于在 NFS 挂载上打开文件,因为它允许跳过可能过时的本地缓存。 它对 I/O 性能有非常实际的影响,因此除非需要,否则不建议使用此标志。

    这不会将 fs.open()fsPromises.open() 变成同步阻塞调用。 如果需要同步操作,应该使用类似 fs.openSync() 的东西。

  • 'w': 打开文件进行写入。 创建(如果它不存在)或截断(如果它存在)该文件。

  • 'wx': 类似于 'w' 但如果路径存在则失败。

  • 'w+': 打开文件进行读写。 创建(如果它不存在)或截断(如果它存在)该文件。

  • 'wx+': 类似于 'w+' 但如果路径存在则失败。

js 复制代码
import fs2 from 'node:fs/promises'

fs2.readFile('./index.txt',{
    encoding:"utf8",
    flag:"",
}).then(result => {
    console.log(result.toString())
})

使用可读流读取 使用场景适合读取大文件

js 复制代码
const readStream = fs.createReadStream('./index.txt',{
    encoding:"utf8"
})

readStream.on('data',(chunk)=>{
    console.log(chunk)
})

readStream.on('end',()=>{
    console.log('close')
})

创建文件夹 如果开启 recursive 可以递归创建多个文件夹

js 复制代码
fs.mkdir('path/test/ccc', { recursive: true },(err)=>{

})

删除文件夹 如果开启recursive 递归删除全部文件夹

js 复制代码
fs.rm('path', { recursive: true },(err)=>{

})

重命名文件 第一个参数原始名称 第二个参数新的名称

js 复制代码
fs.renameSync('./test.txt','./test2.txt')

监听文件的变化 返回监听的事件如change,和监听的内容filename

js 复制代码
fs.watch('./test2.txt',(event,filename)=>{
    
    console.log(event,filename)
})

源码解析

github.com/libuv/libuv

fs的源码是通过 C++ 层的 FSReqCallback 这个类 对libuvuv_fs_t 的一个封装,其实也就是将我们fs 的参数透传给 libuv

mkdir 举例

cc 复制代码
// 创建目录的异步操作函数,通过uv_fs_mkdir函数调用
// 参数:
// - loop: 事件循环对象,用于处理异步操作
// - req: 文件系统请求对象,用于保存操作的状态和结果
// - path: 要创建的目录的路径
// - mode: 目录的权限模式 777 421
// - cb: 操作完成后的回调函数
int uv_fs_mkdir(uv_loop_t* loop,
                uv_fs_t* req,
                const char* path,
                int mode,
                uv_fs_cb cb) {
  INIT(MKDIR);
  PATH;
  req->mode = mode;
  if (cb != NULL)
    if (uv__iou_fs_mkdir(loop, req))
      return 0;
  POST;
}

注意事项

js 复制代码
const fs = require('node:fs')

fs.readFile('./index.txt', {
    encoding: 'utf-8',
    flag: 'r'
}, (err, dataStr) => {
    if (err) throw err
    console.log('fs')
})

setImmediate(() => {
    console.log('setImmediate')
})

为什么先走setImmediate 呢,而不是fs

Node.js 读取文件的时候是使用libuv进行调度的

而setImmediate是由V8进行调度的

文件读取完成后 libuv 才会将 fs的结果 推入V8的队列

相关推荐
旧梦吟2 分钟前
脚本网页 地球演化
前端·算法·css3·html5·pygame
xiaoxue..5 分钟前
哨兵节点与快慢指针解决链表算法难题
前端·javascript·数据结构·算法·链表
这是个栗子5 分钟前
【前端知识点总结】前端跨域问题
前端·跨域·cors
尽欢i11 分钟前
踩过坑才懂:前端生成唯一 ID,别用 Date.now ()了!一行代码搞定
前端·javascript
JS_GGbond11 分钟前
解锁 JavaScript 对象的“魔法宝箱”:这些方法让你玩转对象操作
前端·javascript
是杉杉吖~15 分钟前
《5 分钟上手 React Flex 容器:从 0 搭建响应式卡片列表》
前端·react.js·前端框架
大江东第一深情19 分钟前
Origin 2024 进行语言切换后仍然显示为英文
运维·前端
lxh011323 分钟前
最长公共子序列
前端·数据结构
Можно23 分钟前
ES6扩展运算符:从基础到实战的全方位解析
前端·javascript
豆苗学前端24 分钟前
闭包、现代JS架构的基石(吊打面试官)
前端·javascript·面试