nodejs Buffer與FS、Stream學習

在網絡通信中,拿前端舉例,客戶端發送請求給服務器請求index.html,則服務器會以字符串的形式返回給客戶端html文件,但是像mp3、flv、mp4這些媒體文件實際上是二進制數據文件,所以當客戶端請求時,服務器必須分塊以二進制的形式給客戶端發送數據,傳統的Array數據類型不足以儲存這些數據,Buffer就是為了彌補Array而產生的。
從結構上看Buffer非常像一個數組,它的每個元素儲存2位16進制的數據,一個元素就代表內存的一個字節
Buffer是通過底層的C++申請的

一、Buffer的使用

-使用Buffer不需要引入模塊,它是node的核心模塊
-Buffer中存儲的都是二進制數據,在計算機中所有的二進制數據都是以16進制的方式顯示的
-每個元素的范圍都是00-ff

1.直接從字符串構建

Buffer.from(str)

var str = 'Hello world';
var buf = Buffer.from(str)
> console.log(buf)
<Buffer 48 65 6c 6c 6f 20 77 6f 72 6c 64>
> console.log(buf.length)
11
> buf = Buffer.from('哈哈')
> console.log(buf.length)
6
//

使用buffer.length返回占用的字節長度,而str.length返回字符長度,在uft-8中一個中文占3個字節

2.創建指定大小的緩沖,通過索引進行操作

Buffer.alloc(size)
注意:新的node已經不推薦使用new Buffer 方法創建緩沖
-buffer里的內存空間都是連續的,一旦創建大小不會改變

//分配一個10字節的緩沖
var buf = Buffer.alloc(10)
buf[0] = 88;
buf[1] = 255;
buf[2] = 0xaa;
buf[3] = 256;
buf[4] = 556;
buf[10] = 0xff;
//超出buffer數值范圍的數據會截取后8位進行存儲
//超出buffer地址范圍的數據不會存儲
> console.log(buf)
<Buffer 58 ff aa 00 2c 00 00 00 00 00>
> console.log(buf[2].toString(2))
10101010
//使用buf[x].toString()方法可以將元素的值轉換為別的進制進行顯示
//使用console.log(buf[x])只會打印10進制的值

二、FS與Stream

在服務器中與文件系統的交互是十分重要的,node的fs模塊提供了一些標準文件訪問的API

1.FS的使用

-在fs中所有的文件方法都有同步和異步兩種形式,同步的方法都以Sync結尾
同步文件系統會阻塞程序執行,而異步不會,異步方法通過回調函數來返回數據
首先使用同步方法,文件寫入的流程:打開→寫入→關閉

const fs = require('fs')
var fd = fs.openSync(’hello.txt','w');
//openSync(path,flags[,mode])
//flags 有 /r只讀和 /w寫
//同步方法會返回一個文件描述符,以便對讀取的文件進行操作
console.log(fd)
fs.writeSync(fd,'hello world')
//fs.writeSync(fd,string,position[,encoding])
//position是指從第幾個字節開始
//encoding默認為utf-8
fs.closeSync(fd)

使用異步方式
異步方法結果通過回調函數返回,通過在回調函數里打印arguments可知,回調函數會被傳入2個參數,第一個是error錯誤對象,第二個是文件描述符fd

fs.open('hello.txt','w',function(){
  console.log(arguments)
})
>{ '0': null, '1': 3 }
//fs.open(path,flags[,mode],callback(err,fd))
//nodejs設計思想:錯誤優先,回調函數第一個參數為錯誤對象
fs.open('hello.txt','w',function(err,fd){
  if(!err){
    fs.write(fd,'hello asynchronous',function(err){
      if(!err){
        console.log('寫入成功')
        fs.close(fd,function(err){
          if(!err)
            console.log('關閉啦')
        })
      }
    })
  }
})
//fs.write(fd,string[,position][,encoding],callback(err,written,string))

使用fs.writeFile(path,data,options,callback)和fs.readFile()可以進行更快捷的文件操作

2.使用Stream

-使用fs的方法進行文件寫入都不適合大文件,因為這是一次性的寫入,在寫入文件之前必須要讀取全部的數據然,這樣很容易導致內存溢出。使用流進行讀寫,每次都會只讀取一定量的數據,分多次操作,完成數據傳輸。
-所有的流都支持通過open、close事件監聽流的打開和關閉還有data事件監聽數據的傳輸。其實node中的http模塊里inComingMessage就是一個流的實現,net模塊的socket也是一個流,從它們都存在open、close、data事件類型很容易推測得出。

const fs = require('fs')
//創建一個可寫流
//fs.createWriteStream(path[,options])
var ws = fs.createWriteStream('hello.txt')
ws.one('open',function(){
  console.log('流打開了')
  ws.write('通過可寫流進行文件寫入');
  ws.write('可以分多次寫入');
})
//on(事件,callback)  程序運行時永久有效
//one(事件,callback)  觸發一次后失效
ws.end()
//不能使用ws.close(),ws.close()為關閉流,因為流的寫入是異步的,關閉流會在寫入完成之前
//創建可讀流
var rs = fs.createReadStream('livetune - Satisfaction.mp3')
ws = fs.createWriteStream('music.mp3')
rs.on('data',function(data){
  console.log(data)
  ws.write(data)
})
rs.on('close',function(){
  ws.close()
})
//在可讀流關閉后關閉可寫流

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。