深入基础(四)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>

  

 

posted @ 2017-01-12 16:38  流年过往  阅读(2742)  评论(0编辑  收藏  举报