返回顶部
首页 > 资讯 > 前端开发 > 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://lsjlt.com/news/66490.html(转载时请注明来源链接)

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

猜你喜欢
  • 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
  • nodejs mysql 实现分页的方法
    这两天学习了nodejs mysql 实现分页,很重要,所以,今天添加一点小笔记。 代码如下 var express = require('express'); var router = expre...
    99+
    2022-06-04
    分页 方法 nodejs
  • node.js 利用流实现读写同步,边读边写的方法
    如下所示: //10个数 10个字节,每次读4b,写1b let fs=require("fs"); function pipe(source,target) { //先创建可读流,再创建可写流 ...
    99+
    2022-06-04
    方法 node js
  • BufferedWriter如何使用write方法实现换行
    BufferedWriter write方法实现换行 BufferedWriter对象自带newline()方法可以换行,但如果在字符串中部换行,不想用newline()方法该如何做...
    99+
    2024-04-02
  • BufferedWriter怎么使用write方法实现换行
    小编给大家分享一下BufferedWriter怎么使用write方法实现换行,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!BufferedWriter write方法实现换行BufferedWriter对象自带newlin...
    99+
    2023-06-20
  • 详解nodeJS中读写文件方法的区别
    导言:nodejs中所有与文件相关的操作都在fs模块中,而读写操作又是我们会经常用到的操作,nodejs的fs模块针对读操作为我们提供了readFile,read, createReadStream三个方法...
    99+
    2022-06-04
    详解 区别 文件
  • nodejs中sleep功能实现暂停几秒的方法
    我在网上了解了一下nodejs中sleep功能,搜索了很多关于nodejs中sleep功能介绍,下面我来记录一下,有需要了解的朋友可参考。希望此文章对各位有所帮助。 一 背景 在使用nodejs爬虫的时...
    99+
    2022-06-04
    几秒 功能 方法
  • Nodejs+express中间件实现文件上传的方法
    小编给大家分享一下Nodejs+express中间件实现文件上传的方法,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!用nodejs做项目时需要用到文件上传的功能,...
    99+
    2023-06-14
  • 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
  • 用nodejs实现json和jsonp服务的方法
    一、JSON和JSONP JSONP的全称是JSON with Padding,由于同源策略的限制,XmlHttpRequest只允许请求当前源(协议,域名,端口)的资源。如果要进行跨域请求,我们可以通过使...
    99+
    2022-06-04
    方法 nodejs json
  • nodejs批量下载图片的实现方法
    今天想获取一大批猫的图片,然后就在360流浪器搜索框中输入猫,然后点击图片。就看到了一大波猫的图片:http://image.so.com/i?q=%E7%8...,我在想啊,要是审查元素,一张张手...
    99+
    2022-06-04
    批量 下载图片 方法
  • nodejs部署到腾讯云的实现方法
    目录1、购买腾讯云--轻量应用服务器2、使用winscp进行登录,主机名:公网ip,用户名:root ,密码:上面重置的密码3、安装node环境4、安装pm2(需要node v7以上...
    99+
    2024-04-02
  • iOS中读写锁的简单实现方法实例
    目录废话开篇思考一、对于锁的类型的理解思考二、读写锁的实现逻辑思考三、简单封装读写锁,满足读写逻辑总结废话开篇 iOS 下的多线程的技术的应用衍生出了锁的机制,试想,如果 iOS 下...
    99+
    2022-06-04
    ios 读写锁
  • c# 复写Equals方法的实现
    目录应用情景:什么时候需要重写 Equals() 方法重写 Equals() 方法时的注意事项重写 GetHashCode() 方法时的注意事项应用情景: 很多标准的方法都是利用Ob...
    99+
    2024-04-02
  • Go实现各类限流的方法
    前 言 在开发高并发系统时,我们可能会遇到接口访问频次过高,为了保证系统的高可用和稳定性,这时候就需要做流量限制,你可能是用的 Nginx 这种来控制请求,...
    99+
    2022-06-07
    GO 方法
  • redis实现限流的三种方法
    今天小编给大家分享的是redis实现限流的三种方法,相信很多人都不太了解,为了让大家更加了解,所以给大家总结了以下内容,一起往下看吧。一定会有所收获的哦。第一种:基于Redis的setnx的操作我们在使用R...
    99+
    2024-04-02
  • nodejs读写json文件的简单方法(必看)
    nodejs 读json文件 var fs=reauire('fs'); var file="d:\0.json"; var result=JSON.parse(fs.readFileSync( fil...
    99+
    2022-06-04
    必看 简单 文件
软考高级职称资格查询
推荐阅读
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作