深入基礎(四)Buffer,轉碼


Buffer

    前面提及到一些關於buffer類的問題,當時不是很明確 那么就次機會順便深入探討一下這個東西到底干嘛的出現在什么時候,如何使用.昨天跟朋友聊天他說我每一篇博文內容太長太長了 雖然很精細,但是的確深入的有點多了,so 這篇開始盡量多分幾篇共同討論,減少單一文章內容過多的問題哈.  想起個事兒來這,這兩篇博文其實都是在深挖原生模塊fs,原生如果操作文件的,細心的孩砸都會發現的,對於fs模塊學習還有兩章,我准備這兩張完事兒之后開始學習http模塊 目前項目中有用到部分http模塊的功能,好了不廢話了繼續往下看.

      上篇文章圍繞數據文件操作探討了一下node里面如何操作文件的,但是javascript中只有字符串類型,並不支持二進制(文件操作都是二進制類型的,這也就解決了讀取文件時候為啥不區分文件類別的問題,因為不管啥文件txt,php等等內容都會當做二進制數據取處理,個人理解啊並不代表官方解釋),搶到的node工程師們肯定不能容忍這么low的問題,因此buffer誕生了,buffer說是一個類,更准確的說是一個緩存區域!它在內存中的作用就是單獨存放二進制說的區域.在nodejs中buffer是隨着node一同發布的核心庫,他是存在於V8堆內存之外的一塊原始內存中.而這個內存大小在官方文檔中也有說明:

      目前,V8引擎有一個默認的32位系統512MB內存的限制,在64位系統1.4gb。極限可提高設置- max_old_space_size到最大~ 1024(~ 1 GB)(32位)和4096(~ ~ 4GB)(64位),但建議你把你的單過程分成幾個工人如果你命中內存限制。

      但是Buffer是如果回收的如何設定有效時間期限的真的很難找到相關文章,不過確實會被GC回收,相關文章我就不再這里貼出來了關於這方面的文章真的太少了..似乎沒人去挖這個還是不值得去挖呢?

      buffer類的創建類似於創建數組 :

              var b=new buffer(10); //創建一個10字節的實例

              var b=new buffer([1,2,3])//當然里面也可以是數組

              var b=new buffer("嘿嘿嘿","utf-8")//這個也可以有 而且還設定了編碼方式

     buffer.write

     buf.write(string,[offset],[length],[encoding]),寫入buffer的參數,string 需要寫入的字符串,offset 緩存區開始的索引值,length 寫入長度(當然如果緩存區滿了就只能寫入部分啦),encoding 編碼方式 默認UTF-8

     一個小李子:

buf = new Buffer(256);
len = buf.write("www.w3cschool.cn");

console.log("寫入字節數 : "+  len);

  這個緩存方式有點點像redis,但是它並沒有有效期啊什么什么的,而且格式也是大相徑庭,給我的感覺這個寫入緩存區的就是一個txt文本...啥都是一行里面一直寫下去但是如何找到指定的內容呢?

     bufffer.toString

     是不是感覺很low比...別忘了 人家也是有參數的buffer.toString(encoding,start,end),你寫在什么位置了直接取唄來來上例子看一下瞬間明白了:  

buf = new Buffer(26);
for (var i = 0 ; i < 26 ; i++) {
  buf[i] = i + 97;
}

console.log( buf.toString('ascii'));       // 輸出: abcdefghijklmnopqrstuvwxyz
console.log( buf.toString('ascii',0,5));   // 輸出: abcde
console.log( buf.toString('utf8',0,5));    // 輸出: abcde
console.log( buf.toString(undefined,0,5)); // 使用 'utf8' 編碼, 並輸出: abcde

  好了額,還有很多灰常灰常簡單的方法,例如: 比較compare,合並concat,復制copy,剪切slice 我就不一一介紹了,看看文檔簡直不要再簡單了...http://www.w3cschool.cn/nodejs/x1u41ith.html

     這里我要說一下它的很多很多轉換方法,前面也說到了實際上buffer緩存區域是有大小的而且是有回收機制的(雖然不清楚)大小肯定是有限制的能省點就省點先介紹一下轉換方法:     

     閱讀Buffer的API文檔時,我們會發現更多的是readXXX()writeXXX()開頭的API,具體如下:

  • buf.readUIntLE(offset, byteLength[, noAssert])
  • buf.readUIntBE(offset, byteLength[, noAssert])
  • buf.readIntLE(offset, byteLength[, noAssert])
  • buf.readIntBE(offset, byteLength[, noAssert])
  • buf.readUInt8(offset[, noAssert])
  • buf.readUInt16LE(offset[, noAssert])
  • buf.readUInt16BE(offset[, noAssert])
  • buf.readUInt32LE(offset[, noAssert])
  • buf.readUInt32BE(offset[, noAssert])
  • buf.readInt8(offset[, noAssert])
  • buf.readInt16LE(offset[, noAssert])
  • buf.readInt16BE(offset[, noAssert])
  • buf.readInt32LE(offset[, noAssert])
  • buf.readInt32BE(offset[, noAssert])
  • buf.readFloatLE(offset[, noAssert])
  • buf.readFloatBE(offset[, noAssert])
  • buf.readDoubleLE(offset[, noAssert])
  • buf.readDoubleBE(offset[, noAssert])
  • buf.write(string[, offset][, length][, encoding])
  • buf.writeUIntLE(value, offset, byteLength[, noAssert])
  • buf.writeUIntBE(value, offset, byteLength[, noAssert])
  • buf.writeIntLE(value, offset, byteLength[, noAssert])
  • buf.writeIntBE(value, offset, byteLength[, noAssert])
  • buf.writeUInt8(value, offset[, noAssert])
  • buf.writeUInt16LE(value, offset[, noAssert])
  • buf.writeUInt16BE(value, offset[, noAssert])
  • buf.writeUInt32LE(value, offset[, noAssert])
  • buf.writeUInt32BE(value, offset[, noAssert])
  • buf.writeInt8(value, offset[, noAssert])
  • buf.writeInt16LE(value, offset[, noAssert])
  • buf.writeInt16BE(value, offset[, noAssert])
  • buf.writeInt32LE(value, offset[, noAssert])
  • buf.writeInt32BE(value, offset[, noAssert])
  • buf.writeFloatLE(value, offset[, noAssert])
  • buf.writeFloatBE(value, offset[, noAssert])
  • buf.writeDoubleLE(value, offset[, noAssert])
  • buf.writeDoubleBE(value, offset[, noAssert])

    這些API為在Node.js中操作數據提供了極大的便利。假設我們要將一個整形數值存儲到文件中,比如當前時間戳為1447656645380,如果將其當作一個字符串存儲時,需要占用11字節的空間,而將其轉換為二進制存儲時僅需6字節空間即可: 

var buf = new Buffer(6);

buf.writeUIntBE(1447656645380, 0, 6);
// <Buffer 01 51 0f 0f 63 04>

buf.readUIntBE(0, 6);
// 1447656645380

  這段來自另外一位大神一年前的博客了並且根據取出數據結構被混亂特意寫了一個模塊去解決這個問題lei-proto 有時間膜拜一下,傳送門-->http://cnodejs.org/topic/56499568d28aa64101600fdc

編碼轉換

   這里主要是介紹一下中文轉換我接觸的兩個第三方庫,很多人都在用與其一直用新東西探索未知區域我更願意相信舊的,畢竟千萬人都使用過..不廢話了

     前面經常用到toString()這個方法而node本身對中文以及其他多字節編碼支持並不好,需要第三方庫來協調一下,這里主要介紹一下常用的iconv-lite和encoding

     iconv-lite

     首先先來了解一下iconv, iconv-lite,encoding:

     iconv:是在類Unix系統中一種標准字符集轉換接口,用於在不同字符集編碼之間進行轉換,最早出現在HP-UX系統中,闡釋了node-iconv的起源.

     iconv-lite:是iconv的純js實現,支持的編碼包括node.js原生編碼:utf8, ucs2, ascii, binary, base64;同時支持廣泛使用的單字節編碼:Windows 125x family, ISO-8859 family, IBM/DOS codepages, Macintosh family, KOI8 family, latin1, us-ascii;多字節編碼:gbk, gb2313, Big5, cp950。官方宣稱比node-iconv更快。
 
     encoding:是對node-iconv和iconv-lite的再次封裝,encoding首先調用node-iconv,如果node-iconv無法解析,則調用iconv-lite作為替代方案.相當於iconv-lite的包裝版.
     
     這兩個第三方庫 安裝都一樣sup簡單 npm install iconv-lite  或者 npm install encoding
     
     使用方法我考了別人兩段代碼基本上看看就知道了沒啥特殊的,都是 替代了原有的toString()方法,encoding稍微說一下,先是iconv-lite
     
var iconv = require('iconv-lite');
 
// Convert from an encoded buffer to js string.
str = iconv.decode(buf, 'win1251');
 
// Convert from js string to an encoded buffer.
buf = iconv.encode("Sample input string", 'win1251');
 
// Check if encoding is supported
iconv.encodingExists("us-ascii")

  encoding 需要繞個小丸子,encoding模塊就一個方法convert(),使用方法為:encoding.convert(text, toCharset, fromCharset)。 

             text: 需要轉換的對象,可以為Buffer或者String對象。
             toCharset: 轉換后的編碼。
             fromCharset: 轉換前的編碼,缺省為uft8。
            轉換后的輸入結果為Buffer對象
      
var encoding = require('encoding');
 
var result = encoding.convert("ÕÄÖÜ", "Latin_1");
console.log(result); //<Buffer d5 c4 d6 dc>

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM