iis服务器助手广告广告
返回顶部
首页 > 资讯 > 前端开发 > html >Nodejs中可写流write的实现方法
  • 921
分享到

Nodejs中可写流write的实现方法

2024-04-02 19:04:59 921人浏览 八月长安
摘要

本篇内容主要讲解“nodejs中可写流write的实现方法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“nodejs中可写流write的实现方法”吧!可写流-W

本篇内容主要讲解“nodejs中可写流write的实现方法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习nodejs中可写流write的实现方法”吧!

可写流-Writable

fs.createWriteStream调用例子

  • 首次读取的数据会真实写入目标文件

  • 其余次读取的数据要根据读取数据是否超出highWaterMark ,是的话存入缓存区等待写入目标文件中

const fs = require("fs");
const path = require("path");
const bPath = path.join(__dirname, "b.txt");
let ws = fs.createWriteStream(bPath, {
  flags: "w",
  encoding: "utf-8",
  autoClose: true,
  start: 0,
  highWaterMark: 3,
});
ws.on("open", function (fd) {
  console.log("open", fd);
});
ws.on("close", function () {
  console.log("close");
});
 //string 或者buffer,ws.write 还有一个boolea的返回值
ws.write("1");
//flag 表示 当前要写的值是直接是否直接写入文件,不能超出了单次最大写入值highWaterMark
let flag = ws.write("1");
console.log({ flag });//true
flag = ws.write("1");
console.log({ flag });//false
flag = ws.write("1");
console.log({ flag });//false
flag = ws.write("14444444");
console.log({ flag });//false
ws.end(); //write+close,没有调用 end 是不会调用 触发close的,看到这里的小伙伴可以尝试注释end() 看看close的console是否有打印
  • 效果

Nodejs中可写流write的实现方法

自定义可写流initWriteStream

继承EventEmitter发布订阅
const EventEmitter = require("events");
const fs = require("fs");
class WriteStream extends EventEmitter {}
module.exports = WriteStream;
链表生成队列做文件读取的缓存

链表&队列的实现

https://juejin.cn/post/6973847774752145445

// 用链表 生成队列 对 文件缓存区的读取 进行优化
const Queue = require("./queue");
初始化实例默认数据constructor()
 constructor(path, options = {}) {
    super();
    this.path = path;
    this.flags = options.flags || "w";
    this.encoding = options.encoding || "utf8";
    this.mode = options.mode || 0o666; //默认8进制 ,6 6 6  三组分别的权限是 可读可写
    this.autoClose = options.start || 0;
    this.highWaterMark = options.highWaterMark || 16 * 1024; //默认一次读取16个字节的数据
    this.len = 0; //用于维持有多少数据还没有被写入文件中
    //是否根据等待当前读取的最大文数据 排空后再写入
    this.needDrain = false; //
    // 缓存队列 用于存放 非第一次的文件读取 到的数据,因为第一次读取 直接塞入目标文件中
    // 除第一次 的文件读取数据的都存放再缓存中
    // this.cache = [];
    // 队列做缓存
    this.cache = new Queue();
    // 标记是否是第一次写入目标文件的标识
    this.writing = false;
    this.start = options.start || 0;
    this.offset = this.start; //偏移量
    this.open();
  }
  • this.mode 文件操作权限 默认0o666(0o表示8进制)

    • 3个6所占位置分别对应:文件所属用户对它的权限 ;文件所属用户组用户对它的权限;表示其他用户对它的权限

    • 权限由:r--可读(对应数值4),w--可写(对应数值2),x--可执行(对应数值1,例如文件夹下有 .exe 这样的标识 说明点击可以直接执行)组成

    • 所以默认情况下3组用户对文件的操作权限都是可读可写

open()
  • 调用fs.open()

  • 回调emit实例open方法,fs.open的返回值fd做参数传入

 open() {
    fs.open(this.path, this.flags, this.mode, (err, fd) => {
      this.fd = fd;
      this.emit("open", fd);
    });
  }
write()
  • 转化实例传入的需要写入的文件数据格式为buffer

  • 判断写入数据长度是否大于highWaterMark,如果达到预期后,文件读取到的数据存放再缓存里 不直接写入目标文件(这里要排除是否是第一次读取文件)

  • 执行实例write 传入的cb 并调用clearBuffer 清空缓存

  • 判断 是否是第一次读取,第一次读取 直接写入调用 _write(待实现)

  • 缓存队列尾部offer 当前读取到的数据等待写入目标文件

 write(chunk, encoding = this.encoding, cb = () => {}) {
    //  将数据全部转换成buffer
    chunk = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);

    this.len += chunk.length;
    // console.log({chunk},this.len )
    let returnValue = this.len < this.highWaterMark;
    //当数据写入后,需要在手动的将this.len--
    this.needDrain = !returnValue; //如果达到预期 后 的文件读取 到数据存放再缓存里 不直接写入目标文件
    //清空缓存 对用户传入的回调 进行二次包装
    let userCb = cb;
    cb = () => {
      userCb();
      //清空buffer
      this.clearBuffer();//马上实现
    };

    //此时需要判断 是否是第一次读取,第一次读取 直接写入调用 _write
    if (!this.writing) {
      // 第一次||缓存队列已清空完毕
      this.writing = true;
      // console.log("first write");
      this._write(chunk, encoding, cb);//马上实现
    } else {
    //缓存队列尾部offer 当前读取到的数据等待写入目标文件
      this.cache.offer({
        chunk,
        encoding,
        cb,
      });
    }
    return returnValue;
  }
clearBuffer()依次清空缓存队列
  • 队列执行顺序,先进先出原则

  • this.cache.poll() 依次拿取头部数据执行this._write写入目标文件

  • 缓存队列poll出来的data如果不存在,则说明是第一次写入的行为||缓存队列已清空。this.writing = false; 下次的文件读取可以直接写入目标文件

  • 如果this.needDrain又达到预期,文件读取到数据存放再缓存里 不直接写入目标文件

clearBuffer() {
    //写入成功后 调用 clearBuffer--》写入缓存第一个,第一个完成后,再继续 第二个
    let data = this.cache.poll();
    // console.log('this.cache',this.cache)
    if (data) {
      //有值 写入文件
      this._write(data.chunk, data.encoding, data.cb);
    } else {
      this.writing = false;
      if (this.needDrain) {
        // 如果是缓存,触发drain
        this.emit("drain");
      }
    }
  }
_write()
  • fs.open()是异步的,成功读取后fd会是一个number类型

  • 根据fd的type 决定是否订阅一次open,并回调自己(直到fd类型为number)

  • fd类型为number:调用fs.write,写入当前的chunk,

 _write(chunk, encoding, cb) {
    if (typeof this.fd !== "number") {
      return this.once("open", () => this._write(chunk, encoding, cb));
    }
    fs.write(this.fd, chunk, 0, chunk.length, this.offset, (err, written) => {
      this.offset += written; //维护偏移量
      this.len -= written; //把缓存的个数减少
      cb(); //写入成功
      // console.log(this.cache);
    });
  }

测试自定义的Writable

const WriteStream = require("./initWriteStream");

let ws = new WriteStream(bPath, {
  highWaterMark: 3,
});

let i = 0;
function write() {
  //写入0-9个
  let flag = true;
  while (i < 10 && flag) {
    flag = ws.write(i++ + "");
     console.log(flag);
  }
}
ws.on("drain", function () {
  // 只有当我们写入的数据达到预期,并且数据被清空后才会触发drain ⌚️
  console.log("写完了");
  write();
});

write();
  • 10个数字,依次写入,3次达到最大预期值,然后依次清空了3次缓存结果符合预期

Nodejs中可写流write的实现方法

  • 目标文件中查看是否正确写入了我们预期的数值

Nodejs中可写流write的实现方法

到此,相信大家对“Nodejs中可写流write的实现方法”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

--结束END--

本文标题: Nodejs中可写流write的实现方法

本文链接: https://www.lsjlt.com/news/66490.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Nodejs中可写流write的实现方法
    本篇内容主要讲解“Nodejs中可写流write的实现方法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Nodejs中可写流write的实现方法”吧!可写流-W...
    99+
    2024-04-02
  • Python中怎么使用write()方法写文字
    在Python中,可以使用write()方法写入文字到文件中。首先,需要打开一个文件,可以使用open()函数来完成。然后,可以使用...
    99+
    2023-10-12
    Python
  • Node中的可读流和可写流实例代码分析
    这篇“Node中的可读流和可写流实例代码分析”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Node中的可读流和可写流实例代码...
    99+
    2023-07-05
  • BufferedWriter怎么使用write方法实现换行
    小编给大家分享一下BufferedWriter怎么使用write方法实现换行,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!BufferedWriter write方法实现换行BufferedWriter对象自带newlin...
    99+
    2023-06-20
  • BufferedWriter如何使用write方法实现换行
    BufferedWriter write方法实现换行 BufferedWriter对象自带newline()方法可以换行,但如果在字符串中部换行,不想用newline()方法该如何做...
    99+
    2024-04-02
  • Nodejs+express中间件实现文件上传的方法
    小编给大家分享一下Nodejs+express中间件实现文件上传的方法,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!用nodejs做项目时需要用到文件上传的功能,...
    99+
    2023-06-14
  • nodejs部署到腾讯云的实现方法
    目录1、购买腾讯云--轻量应用服务器2、使用winscp进行登录,主机名:公网ip,用户名:root ,密码:上面重置的密码3、安装node环境4、安装pm2(需要node v7以上...
    99+
    2024-04-02
  • php中runtime不可写的解决方法
    这篇文章主要介绍了php中runtime不可写的解决方法,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。php的框架有哪些php的框架:1、Laravel,Laravel是一款...
    99+
    2023-06-15
  • android中NFC读写功能的实现方法
    本文实例为大家分享了android中NFC读写功能的具体代码,供大家参考,具体内容如下 首先检查一下设备是否支持NFC功能 private void checkNFCFuncti...
    99+
    2024-04-02
  • c# 复写Equals方法的实现
    目录应用情景:什么时候需要重写 Equals() 方法重写 Equals() 方法时的注意事项重写 GetHashCode() 方法时的注意事项应用情景: 很多标准的方法都是利用Ob...
    99+
    2024-04-02
  • Nodejs读写文件的操作方法有哪些
    这篇“Nodejs读写文件的操作方法有哪些”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Nodejs读写文件的操作方法有哪些...
    99+
    2023-07-04
  • Java中文件的读写方法之IO流详解
    目录1.File类1.1File类概述和构造方法1.2File类创建功能1.3File类判断和获取功能1.4File类删除功能2.递归2.1递归2.2递归求阶乘2.3递归遍历目录3....
    99+
    2024-04-02
  • React实现单向数据流的方法
    目录为什么React采用单向数据流设计一、原因二、什么是React单向数据流三、如何使用React单向数据流1. 定义组件2. 定义Props属性3. 子组件接收并使用Props属性...
    99+
    2023-05-16
    React 单向数据流
  • 使用Java实现Redis限流的方法
    1、概述   限流的含义是在单位时间内确保发往某个模块的请求数量小于某个数值,比如在实现秒杀功能时,需要确保在10秒内发往支付模块的请求数量小于500个。限流...
    99+
    2024-04-02
  • Redis限流的实现方法有哪些
    本篇内容主要讲解“Redis限流的实现方法有哪些”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Redis限流的实现方法有哪些”吧!一、简单的限流基本原理当系统处理能力有限,如何组织计划外的请求对...
    99+
    2023-06-22
  • nodejs控制台打印高亮代码的实现方法
    前言 当代码运行报错时,我们会打印错误,错误中有堆栈信息,可以定位到对应的代码位置。但有的时候我们希望能够更直接准确的打印报错位置的代码。比如这样: 这个可以使用 @babel/c...
    99+
    2024-04-02
  • php实现字符转小写的方法
    小编给大家分享一下php实现字符转小写的方法,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!php实现字符转小写的方法:首先创建一个PHP示例文件;然后定义一个字符...
    99+
    2023-06-14
  • C#方法重写怎么实现
    这篇文章主要介绍“C#方法重写怎么实现”,在日常操作中,相信很多人在C#方法重写怎么实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C#方法重写怎么实现”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!C#...
    99+
    2023-06-17
  • Nodejs中多线程的操作方法
    这篇文章主要介绍“Nodejs中多线程的操作方法”,在日常操作中,相信很多人在Nodejs中多线程的操作方法问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Nodejs中多线程...
    99+
    2024-04-02
  • Pytorch可视化的几种实现方法
    目录一,利用 tensorboardX 可视化网络结构二,利用 vistom 可视化三,利用pytorchviz可视化网络结构一,利用 tensorboardX 可视化网络结构 参...
    99+
    2024-04-02
软考高级职称资格查询
推荐阅读
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作