本篇文章給大家剖析一下Nodejs中的文件流,希望對(duì)大家有所幫助!
文件流
由于電腦中的各種介質(zhì)讀存的速度不同、容量大小不同,因此可能在操作中會(huì)有一方存在長期等待的狀態(tài)
文件流主要有三種,分別為輸入流(Readable)、輸出流(Writeable)、雙工流(Duplex)。其中還有一種流不常用那就是 轉(zhuǎn)換流(Transform)
在 node 中提供了 stream 模塊,這個(gè)模塊中有兩個(gè)類實(shí)例:Readable 和 Writable,流中都會(huì)繼承這兩個(gè)類,因此會(huì)有很多共同的方法等。
可讀流(Readable)
輸入流:數(shù)據(jù)從源頭流向內(nèi)存,把磁盤里面的數(shù)據(jù)傳輸?shù)絻?nèi)存里面。
createReadStream
fs.createReadStream(路徑, 配置)
在配置里面有:encoding(編碼方式)、start(起始讀取字節(jié))、end(結(jié)束讀取字節(jié))、highWaterMark(每次讀取量)
highWaterMark:如果encoding有值,該數(shù)量表示一個(gè)字符數(shù);如果encoding為null,該數(shù)量表示字節(jié)數(shù)
返回一個(gè)Readable的子類ReadStream
const readable = fs.createReadStream(filename, { encoding: 'utf-8', start: 1, end: 2, // highWaterMark: });
注冊事件
readable.on(事件名,處理函數(shù))
readable.on('open', (err, data)=> { // console.log(err); console.log('文件打開了'); }) readable.on('error', (data, err) => { console.log(data, err); console.log('讀取文件發(fā)生錯(cuò)誤'); }) readable.on('close', (data, err) => { // console.log(data, err); console.log('文件關(guān)閉'); }) readable.close() // 手動(dòng)觸發(fā)通過 readable.close()或者在文件讀取完畢之后自動(dòng)關(guān)閉--autoClose配置項(xiàng)默認(rèn)為 true readable.on('data', (data) => { console.log(data); console.log('文件正在讀取'); }) readable.on('end', ()=>{ console.log('文件讀取完畢'); })
暫停讀取
readable.pause() 暫停讀取,會(huì)觸發(fā) pause 事件
恢復(fù)讀取
readable.resume() 恢復(fù)讀取,會(huì)觸發(fā) resume 事件
可寫流
const ws = fs.createWriteStream(filename[, 配置])
ws.write(data)
寫入一個(gè)數(shù)據(jù),data 可以使字符串也可以是Buffer,返回一個(gè)布爾值。
如果返回的是 true 表示寫入通道沒有被占滿,接下來的數(shù)據(jù)可以直接寫入,寫入通道就是配置中的 highWaterMark 表示的大小。
如果返回的是false 表示寫入通道占滿,其余字符開始等待,出現(xiàn)背壓情況。
const ws = fs.createWriteStream(filename, { encoding: 'utf-8', highWaterMark: 2 }) const flag = ws.write('劉'); console.log(flag); // false 這里雖然只會(huì)執(zhí)行一次,但是在通道有空余空間的時(shí)候就會(huì)繼續(xù)寫入,并不在返回 值。 ws.write() 只會(huì)返回一次值。 const flag = ws.write('a'); console.log(flag); const flag1 = ws.write('a'); console.log(flag1); const flag2 = ws.write('a'); console.log(flag2); const flag3 = ws.write('a'); console.log(flag3); 輸出順序:true、false、false、false 第二次寫入的時(shí)候已經(jīng)占了兩字節(jié),第三次寫入后直接占滿了,所以返回false
使用流復(fù)制粘貼文件,并解決背壓問題
const filename = path.resolve(__dirname, './file/write.txt'); const wsfilename = path.resolve(__dirname, './file/writecopy.txt'); const ws = fs.createWriteStream(wsfilename); const rs = fs.createReadStream(filename) rs.on('data', chumk => { const falg = ws.write(chumk); if(!falg) { rs.pause(); } }) ws.on('drain', () => { rs.resume(); }) rs.on('close', () => { ws.end(); console.log('copy end'); })
pipe
使用 pipe 也可以直接將 可讀流 和 寫入流串聯(lián)起來,也可以解決背壓問題
rs.pipe(ws); rs.on('close', () => { ws.end(); console.log('copy end'); })
學(xué)習(xí)下來,感覺文件流在大量文件讀寫的時(shí)候是很方便的,并且可以做到快速高效,相比于writeFile
和readFile
效率要高很多,正確處理也不會(huì)有很大的阻塞出現(xiàn)。