免费观看又色又爽又黄的小说免费_美女福利视频国产片_亚洲欧美精品_美国一级大黄大色毛片

Nodejs中可寫流write的實(shí)現(xiàn)方法

本篇內(nèi)容主要講解“Nodejs中可寫流write的實(shí)現(xiàn)方法”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“Nodejs中可寫流write的實(shí)現(xiàn)方法”吧!

牟平網(wǎng)站建設(shè)公司成都創(chuàng)新互聯(lián)公司,牟平網(wǎng)站設(shè)計(jì)制作,有大型網(wǎng)站制作公司豐富經(jīng)驗(yàn)。已為牟平成百上千家提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\外貿(mào)網(wǎng)站制作要多少錢,請找那個售后服務(wù)好的牟平做網(wǎng)站的公司定做!

可寫流-Writable

fs.createWriteStream調(diào)用例子

  • 首次讀取的數(shù)據(jù)會真實(shí)寫入目標(biāo)文件

  • 其余次讀取的數(shù)據(jù)要根據(jù)讀取數(shù)據(jù)是否超出highWaterMark ,是的話存入緩存區(qū)等待寫入目標(biāo)文件中

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 表示 當(dāng)前要寫的值是直接是否直接寫入文件,不能超出了單次最大寫入值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,沒有調(diào)用 end 是不會調(diào)用 觸發(fā)close的,看到這里的小伙伴可以嘗試注釋end() 看看close的console是否有打印
  • 效果

Nodejs中可寫流write的實(shí)現(xiàn)方法

自定義可寫流initWriteStream

繼承EventEmitter發(fā)布訂閱
const EventEmitter = require("events");
const fs = require("fs");
class WriteStream extends EventEmitter {}
module.exports = WriteStream;
鏈表生成隊(duì)列做文件讀取的緩存

鏈表&隊(duì)列的實(shí)現(xiàn)

https://juejin.cn/post/6973847774752145445

// 用鏈表 生成隊(duì)列 對 文件緩存區(qū)的讀取 進(jìn)行優(yōu)化
const Queue = require("./queue");
初始化實(shí)例默認(rèn)數(shù)據(jù)constructor()
 constructor(path, options = {}) {
    super();
    this.path = path;
    this.flags = options.flags || "w";
    this.encoding = options.encoding || "utf8";
    this.mode = options.mode || 0o666; //默認(rèn)8進(jìn)制 ,6 6 6  三組分別的權(quán)限是 可讀可寫
    this.autoClose = options.start || 0;
    this.highWaterMark = options.highWaterMark || 16 * 1024; //默認(rèn)一次讀取16個字節(jié)的數(shù)據(jù)
    this.len = 0; //用于維持有多少數(shù)據(jù)還沒有被寫入文件中
    //是否根據(jù)等待當(dāng)前讀取的最大文數(shù)據(jù) 排空后再寫入
    this.needDrain = false; //
    // 緩存隊(duì)列 用于存放 非第一次的文件讀取 到的數(shù)據(jù),因?yàn)榈谝淮巫x取 直接塞入目標(biāo)文件中
    // 除第一次 的文件讀取數(shù)據(jù)的都存放再緩存中
    // this.cache = [];
    // 隊(duì)列做緩存
    this.cache = new Queue();
    // 標(biāo)記是否是第一次寫入目標(biāo)文件的標(biāo)識
    this.writing = false;
    this.start = options.start || 0;
    this.offset = this.start; //偏移量
    this.open();
  }
  • this.mode 文件操作權(quán)限 默認(rèn)0o666(0o表示8進(jìn)制)

    • 3個6所占位置分別對應(yīng):文件所屬用戶對它的權(quán)限 ;文件所屬用戶組用戶對它的權(quán)限;表示其他用戶對它的權(quán)限

    • 權(quán)限由:r--可讀(對應(yīng)數(shù)值4),w--可寫(對應(yīng)數(shù)值2),x--可執(zhí)行(對應(yīng)數(shù)值1,例如文件夾下有 .exe 這樣的標(biāo)識 說明點(diǎn)擊可以直接執(zhí)行)組成

    • 所以默認(rèn)情況下3組用戶對文件的操作權(quán)限都是可讀可寫

open()
  • 調(diào)用fs.open()

  • 回調(diào)emit實(shí)例open方法,fs.open的返回值fd做參數(shù)傳入

 open() {
    fs.open(this.path, this.flags, this.mode, (err, fd) => {
      this.fd = fd;
      this.emit("open", fd);
    });
  }
write()
  • 轉(zhuǎn)化實(shí)例傳入的需要寫入的文件數(shù)據(jù)格式為buffer

  • 判斷寫入數(shù)據(jù)長度是否大于highWaterMark,如果達(dá)到預(yù)期后,文件讀取到的數(shù)據(jù)存放再緩存里 不直接寫入目標(biāo)文件(這里要排除是否是第一次讀取文件)

  • 執(zhí)行實(shí)例write 傳入的cb 并調(diào)用clearBuffer 清空緩存

  • 判斷 是否是第一次讀取,第一次讀取 直接寫入調(diào)用 _write(待實(shí)現(xiàn))

  • 緩存隊(duì)列尾部offer 當(dāng)前讀取到的數(shù)據(jù)等待寫入目標(biāo)文件

 write(chunk, encoding = this.encoding, cb = () => {}) {
    //  將數(shù)據(jù)全部轉(zhuǎn)換成buffer
    chunk = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);

    this.len += chunk.length;
    // console.log({chunk},this.len )
    let returnValue = this.len < this.highWaterMark;
    //當(dāng)數(shù)據(jù)寫入后,需要在手動的將this.len--
    this.needDrain = !returnValue; //如果達(dá)到預(yù)期 后 的文件讀取 到數(shù)據(jù)存放再緩存里 不直接寫入目標(biāo)文件
    //清空緩存 對用戶傳入的回調(diào) 進(jìn)行二次包裝
    let userCb = cb;
    cb = () => {
      userCb();
      //清空buffer
      this.clearBuffer();//馬上實(shí)現(xiàn)
    };

    //此時需要判斷 是否是第一次讀取,第一次讀取 直接寫入調(diào)用 _write
    if (!this.writing) {
      // 第一次||緩存隊(duì)列已清空完畢
      this.writing = true;
      // console.log("first write");
      this._write(chunk, encoding, cb);//馬上實(shí)現(xiàn)
    } else {
    //緩存隊(duì)列尾部offer 當(dāng)前讀取到的數(shù)據(jù)等待寫入目標(biāo)文件
      this.cache.offer({
        chunk,
        encoding,
        cb,
      });
    }
    return returnValue;
  }
clearBuffer()依次清空緩存隊(duì)列
  • 隊(duì)列執(zhí)行順序,先進(jìn)先出原則

  • this.cache.poll() 依次拿取頭部數(shù)據(jù)執(zhí)行this._write寫入目標(biāo)文件

  • 緩存隊(duì)列poll出來的data如果不存在,則說明是第一次寫入的行為||緩存隊(duì)列已清空。this.writing = false; 下次的文件讀取可以直接寫入目標(biāo)文件

  • 如果this.needDrain又達(dá)到預(yù)期,文件讀取到數(shù)據(jù)存放再緩存里 不直接寫入目標(biāo)文件

clearBuffer() {
    //寫入成功后 調(diào)用 clearBuffer--》寫入緩存第一個,第一個完成后,再繼續(xù) 第二個
    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) {
        // 如果是緩存,觸發(fā)drain
        this.emit("drain");
      }
    }
  }
_write()
  • fs.open()是異步的,成功讀取后fd會是一個number類型

  • 根據(jù)fd的type 決定是否訂閱一次open,并回調(diào)自己(直到fd類型為number)

  • fd類型為number:調(diào)用fs.write,寫入當(dāng)前的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; //維護(hù)偏移量
      this.len -= written; //把緩存的個數(shù)減少
      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 () {
  // 只有當(dāng)我們寫入的數(shù)據(jù)達(dá)到預(yù)期,并且數(shù)據(jù)被清空后才會觸發(fā)drain ??
  console.log("寫完了");
  write();
});

write();
  • 10個數(shù)字,依次寫入,3次達(dá)到最大預(yù)期值,然后依次清空了3次緩存結(jié)果符合預(yù)期

Nodejs中可寫流write的實(shí)現(xiàn)方法

  • 目標(biāo)文件中查看是否正確寫入了我們預(yù)期的數(shù)值

Nodejs中可寫流write的實(shí)現(xiàn)方法

到此,相信大家對“Nodejs中可寫流write的實(shí)現(xiàn)方法”有了更深的了解,不妨來實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

分享文章:Nodejs中可寫流write的實(shí)現(xiàn)方法
路徑分享:http://m.newbst.com/article34/pooepe.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供云服務(wù)器服務(wù)器托管全網(wǎng)營銷推廣App開發(fā)ChatGPT定制網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

營銷型網(wǎng)站建設(shè)