日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

node 流学习笔记 - 可写流

發布時間:2025/3/21 编程问答 49 豆豆
生活随笔 收集整理的這篇文章主要介紹了 node 流学习笔记 - 可写流 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

可寫流

  • 可寫流沒有會創建,有內容的話會清空
  • 默認情況下一次能寫 16 * 1024
  • 緩存區,第一次寫入是真的向文件里寫入,第二次在寫入的時候放入到了緩存區里
  • 寫入時候返回一個boolean類型,返回為false時不要在寫入
  • 當內存和正在寫入的內容消耗完后會觸發 drain 事件。

讀取的時候,讀到幾個就發射出幾個,而可寫流默認情況下一次能寫入 16 * 1024。舉例:讀取 30 個,但是寫一次寫入3個,多出來的 27個則放入到緩存區里。第一次是真往文件里寫入,后面則全部放到緩存區中,寫完后則清空緩存區。

let fs = require('fs');let ws = fs.createWriteStream('./2.text', {flags: 'w', // 模式encoding: 'utf8', // 編碼start: 0, // 從哪兒開始寫highWaterMark: 3 // 最高的水位線 16 * 1024 });// 寫入 寫入的內容必須是字符串或者buffer // flag 表示是否還有緩存空間 當寫入的次數大于等于 highWaterMark 則返回flase // 可讀流配合可寫流使用。flag 為了保證讀取和寫入可以節約內存,而不是瘋狂的讀 let flag = ws.write('1', 'utf8', () => { });復制代碼

舉例子:一次能寫3個,9個數字,先寫入 9 8 7 然后等一等,等寫完后在繼續寫入 6 5 4 。。。。比如一個人能吃饅頭一次最多吃3個,如果不停的給他饅頭,嘴里沒有吃完則將饅頭放到地上(緩存區里去)。等吃完在去拿來吃。

let fs = require('fs');let ws = fs.createWriteStream('./3.text', {flags: 'w', // 模式encoding: 'utf8', // 編碼start: 0, // 從哪兒開始寫highWaterMark: 3 // 最高的水位線 16 * 1024 });let i = 9; function write() {// 是否可寫入let flag = true;while(flag && i >= 0) {// 第一次 9 8 7 當是 7 的時候 flag 為falseflag = ws.write(i-- + '');} } // 只有嘴里塞滿了吃完了。才會觸發 // drain 觸發時機,只有當嘴(highWaterMark)滿了,才可能觸發 drain // 只有當嘴里的和地上的(內存里)都吃完了,才會觸發 drain 方法 ws.on('drain', () => {console.log('吃完了。');// 繼續吃write(); }) write(); 復制代碼

可寫流原理

  • 默認屬性
constructor(path, options = {}) {super();this.path = path;this.flags = options.flags || 'w';this.encoding = optins.encoding || 'utf8';this.start = options.start || 0;this.mode = options.mode || 0o666;this.autoClose = options.autoClose || true;this.highWaterMark = options.highWaterMark || 16 * 1024;// 先打開文件 異步調用 觸發 open 事件后拿到 fdthis.open(); } 復制代碼
  • open 打開文件
open() {fs.open(this.path, this.flags, this.mode, (err, fd) => {if (err) {// 是否需要關閉if(this.autoClose) {// 如果自動關閉就銷毀文件描述符 fdthis.destory();}this.emit('error', err);return;}this.fd = fd;this.emit('open', this.fd);}); } 復制代碼
  • 關閉文件
// 關閉文件 destory() {if(typeof this.fd !== 'number') {// 沒有打開過this.emit('close');} else {fs.close(this.fd, () => {this.emit('close');});} } 復制代碼
  • write 寫入
// 客戶調用的是write方法寫入內容 write(chunk, encoding = this.encoding, callback) {// 將 chunk 變成bufferchunk = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);this.len += chunk.length; // 維護緩存的長度let ret = this.len < this.highWaterMark;if (!ret) {this.needDrain = true; // 需要觸發drain事件}if (this.writing) {// 正在寫入應該放到內存中this.cach.push({chunk,encoding,callback});} else {// 第一次寫入this._write(chunk, encoding, ()=>this.clearBuffer());}return ret; // 表示能不能繼續寫。false 表示下次寫的時候就要占用更多內存 } 復制代碼
  • _write && clearBuffer 方法實現
_write(chunk, encoding, buffer) {// write 同步調用 fd 還沒獲取到,獲取到fd后在執行writeif (typeof this.fd !== 'number') {return this.once('open', this._write(chunk, encoding, buffer));}fs.write(this.fd, chunk, 0, chunk.length, this.pos, (err, byteWritten) => {this.pos += byteWritten;this.len -= byteWritten; // 每次寫入后就要在內存中減少 相當于把饅頭吃掉了this.clearBuffer(); // 第一次寫完}); }clearBuffer() {let buffer = this.cache.shift();if (buffer) {// 緩存里有this._write(buffer.chunk, buffer.encoding, () => this.clearBuffer());} else {// 緩存里沒有// 需要出發drain事件if (this.needDrain) {this.writing = false; // 不需要再寫入到內存里。this.needDrain = false;this.emit('drain');}} } 復制代碼

完整代碼

<!--WriteStream.js--> let fs = require('fs'); let EventEmitter = require('events');class WriteStream extends EventEmitter {constructor(path, options = {}) {super();this.path = path;this.flags = options.flags || 'w';this.encoding = options.encoding || 'utf8';this.start = options.start || 0;this.pos = this.start;this.mode = options.mode || 0o666;this.autoClose = options.autoClose || true;this.highWaterMark = options.highWaterMark || 16 * 1024;// 先打開文件 異步調用 觸發 open 事件后拿到 fdthis.open();// 寫文件的時候需要的參數// 第一次寫入是真的往文件里寫入this.writing = false; // 默認第一次沒有正在寫入// 緩存區this.cache = [];// 維護一個變量 表示緩存的長度this.len = 0;// 是否觸發 drain 事件this.needDrain = false;}// clearBuffer() {let buffer = this.cache.shift();if (buffer) {// 緩存里有this._write(buffer.chunk, buffer.encoding, () => this.clearBuffer());} else {// 緩存里沒有// 需要出發drain事件if (this.needDrain) {this.writing = false; // 不需要再寫入到內存里。this.needDrain = false;this.emit('drain');}}}_write(chunk, encoding, clearBuffer) {// write 同步調用 fd 還沒獲取到,獲取到fd后在執行writeif (typeof this.fd !== 'number') {return this.once('open', ()=>this._write(chunk, encoding, clearBuffer));}fs.write(this.fd, chunk, 0, chunk.length, this.pos, (err, byteWritten) => {this.pos += byteWritten;this.len -= byteWritten; // 每次寫入后就要在內存中減少 相當于把饅頭吃掉了this.clearBuffer(); // 第一次寫完});}// 客戶調用的是write方法寫入內容write(chunk, encoding = this.encoding, callback) {// 將 chunk 變成bufferchunk = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);this.len += chunk.length; // 維護緩存的長度let ret = this.len < this.highWaterMark;if (!ret) {this.needDrain = true; // 需要觸發drain事件}if (this.writing) {// 正在寫入應該放到內存中this.cache.push({chunk,encoding,callback});} else {this.writing = true;// 第一次寫入this._write(chunk, encoding, ()=>this.clearBuffer());}return ret; // 表示能不能繼續寫。false 表示下次寫的時候就要占用更多內存}// 關閉文件destory() {if(typeof this.fd !== 'number') {// 沒有打開過this.emit('close');} else {fs.close(this.fd, () => {this.emit('close');});}}// 打開文件open() {fs.open(this.path, this.flags, this.mode, (err, fd) => {if (err) {// 是否需要關閉if(this.autoClose) {// 如果自動關閉就銷毀文件描述符 fdthis.destory();}this.emit('error', err);return;}this.fd = fd;this.emit('open', this.fd);});}}module.exports = WriteStream;<!--應用--> let fs = require('fs'); let WS = require('./WriteStream'); let ws = new WS('./3.text', {flags: 'w', // 文件如果不存在則創建,文件存在則清空highWaterMark: 3, // 設置當前緩存區大小即嘴有多大encoding: 'utf8', // 文件里存放的是二進制start: 0,autoClose: true, // 自動關閉mode: 0o666 // 可讀可寫 });let i = 9;function write() {let flag = true;while(flag && i >= 0) {flag = ws.write(i-- + '', 'utf8');} } // drain 觸發時機,只有當嘴(highWaterMark)滿了,才可能觸發 drain // 只有當嘴里的和地上的(內存里)都吃完了,才會觸發 drain 方法 write(); ws.on('drain', () => {console.log('寫完了');write(); }); 復制代碼

總結

以上是生活随笔為你收集整理的node 流学习笔记 - 可写流的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。