当年是看了朴灵的九浅一深 NodeJS 入门的 Node, 朴大大的书讲实践很少更多的篇幅用在了讲原理上,道理听了那么多,后来开始在前端工程领域使用 NodeJS 却处处掣肘,总结原因发现 NodeJS 中难的部分无非是文件和网络,文件操作和网络都依赖了一个很重要的对象—— Stream,这恰恰是朴大大书中没有提及的。

Buffer 朴大大在书中是有提到过的,但因为流实际上就是在处理 Buffer,所以还是要简单总结一下。

什么是 Buffer

如同官方 API 中介绍的那样,在 ES6 引入 TypedArray 之前,JavaScript 没有读取或者操作二进制数据流的机制。 Buffer 类作为 NodeJS API 的一部分被引入,以便能够和 TCP 等网络流和文件流等进行交互。

现在 TypedArray 已经被添加到了 ES6 中,Buffer 类以一种更优化和适用于 NodeJS 操作的方式实现了 Unit8Array API。

总而言之,Buffer 类是用来处理二进制数据,因为太常用了,所以直接放在了全局变量里,使用的时候无需 require。

Buffer 类的实例类似于整型数组,不过缓冲区的大小在创建时确定,不能调整。Buffer 对象不同之处在于它不经 V8 的内存分配机制,Buffer 是一个 JavaScript 和 C++ 结合的模块,内存由 C++ 申请,JavaScript 分配。

关于 Buffer 内存分配相关知识不展开讨论,感兴趣同学可以看看朴老湿的书。

实例化 Buffer

在 NodeJS v6 之前都是通过调用构造函数的方式实例化 Buffer,根据参数返回不同结果。处于安全性原因,这种方式在 v6 后的版本中已经被废除,提供了

  • Buffer.from()
  • Buffer.alloc()
  • Buffer.allocUnsafe()

三个单独的,职责清晰的函数处理实例化 Buffer 的工作。

  • Buffer.from(array):返回一个内容包含所提供的字节副本的 Buffer,数组中每一项是一个表示八位字节的数字,所以值必须在 0 ~ 255 之间,否则会取模
  • Buffer.from(arrayBuffer):返回一个与给定的 ArrayBuffer 共享内存的新 Buffer
  • Buffer.from(buffer):返回给定 Buffer 的一个副本 Buffer
  • Buffer.from(string [, encoding]):返回一个包含给定字符串的 Buffer
  • Buffer.alloc(size [, fill [, encoding]]):返回指定大小并且“已填充”的 Buffer
  • Buffer.allocUnsafe(size):返回指定大小的 Buffer,内容必须用 buf.fill(0) 等方法填充
// 0x 表示 16 进制

Buffer.from([1, 2, 3]) // [0x1, 0x2, 0x3]

Buffer.from('test', 'utf-8') // [0x74, 0x65, 0x73, 0x74]

Buffer.alloc(5, 1) // [0x1, 0x1, 0x1, 0x1, 0x1]

Buffer.allocUnsafe(5); // 值不确定,后面详谈

Buffer.allocUnsafe() 的执行会快于 Buffer.alloc() 看名字很不安全,确实也不安全。

当调用 Buffer.allocUnsafe() 时分配的内存段尚未初始化(不归零),这样分配内存速度很块,但分配到的内存片段可能包含旧数据。如果在使用的时候不覆盖这些旧数据就可能造成内存泄露,虽然速度快,尽量避免使用。

编码

Buffer 支持以下几种编码格式

  • ascii
  • utf8
  • utf16le
  • base64
  • binary
  • hex

Buffer 和 String 转换

字符串转为 Buffer 比较简单

Buffer.from(string [, encoding])

同时 Buffer 实例也有 toString 方法将 Buffer 转为字符串

buf.toString([encoding[, start[, end]]])

Buffer 拼接

使用 concat 方法可以讲多个 Buffer 实例拼接为一个 Buffer 实例

Buffer.concat(list[, totalLength])

StringDecoder

在 NodeJS 中一个汉字由三个字节表示,如果我们处理中文字符的时候使用了不是3的倍数的字节数就会造成字符拼接乱码问题。

const buf = Buffer.from('中文字符串!');

for(let i = 0; i < buf.length; i+=5){
var b = Buffer.allocUnsafe(5);
buf.copy(b, 0, i);
console.log(b.toString());
}

这样可以看到结果中出现了乱码

但如果使用 string_decoder 模块便可以解决这个问题

const StringDecoder = require('string_decoder').StringDecoder;
const decoder = new StringDecoder('utf8'); const buf = Buffer.from('中文字符串!'); for(let i = 0; i < buf.length; i+=5){
var b = Buffer.allocUnsafe(5);
buf.copy(b, 0, i);
console.log(decoder.write(b));
}

StringDecoder 在得到编码后,知道宽字节在utf-8下占3个字节,所以在处理末尾不全的字节时,会保留到第二次 write()。目前只能处理UTF-8、Base64 和 UCS-2/UTF-16LE。

Buffer 其它常用 API

还有一些 Buffer 常用的 API

  • Buffer.isBuffer:判断对象是否为 Buffer
  • Buffer.isEncoding:判断 Buffer 对象编码
  • buf.length:返回 内存为此 Buffer 实例所申请的字节数,并不是 Buffer 实例内容的字节数
  • buf.indexOf:和数组的 indexOf 类似,返回某字符串、acsii 码或者 buf 在改 buf 中的位置
  • buf.copy:将一个 buf 的(部分)内容复制到另外一个 buf 中

NodeJS stream 一:Buffer的更多相关文章

  1. nodejs stream & buffer 互相转换

    stream 转 buffer function streamToBuffer(stream) { return new Promise((resolve, reject) => { let b ...

  2. 理解 nodeJS 中的 buffer,stream

    在Node.js开发中,当遇到 buffer,stream,和二进制数据处理时,你是否像我一样,总是感到困惑?这种感觉是否会让你认为不了解它们,以为它们不适合你,认为而这些是Node.js作者们的事情 ...

  3. nodejs stream 手册学习

    nodejs stream 手册 https://github.com/jabez128/stream-handbook 在node中,流可以帮助我们将事情的重点分为几份,因为使用流可以帮助我们将实现 ...

  4. Nodejs stream模块-翻译

    花了两天时间尝试按照自己的话翻译了一下stream模块,以下内容皆翻译于:https://nodejs.org/api/stream.html. 目录 1  Stream(流)     1.1     ...

  5. NodeJS Stream流

    NodeJS Stream流 流数据在网络通信中至关重要,nodeJS用Stream提供了一个抽象接口,node中有很多对象实现了这个接口,提供统一的操作体验 基本流类型 NodeJS中,Stream ...

  6. nodejs缓冲模块buffer相关资料

    buffer模块的详细使用教程 浅析nodejs的buffer类 深入浅出NodeJS--Buffer Node Buffer/Stream 内存策略分析

  7. NodeJS Stream 三:readable

    什么是可读流 可读流是生产数据用来供程序消费的流.我们常见的数据生产方式有读取磁盘文件.读取网络请求内容等,看一下前面介绍什么是流用的例子: const rs = fs.createReadStrea ...

  8. NodeJS Stream 五:双工流

    双工流就是同时实现了 Readable 和 Writable 的流,即可以作为上游生产数据,又可以作为下游消费数据,这样可以处于数据流动管道的中间部分,即 rs.pipe(rws1).pipe(rws ...

  9. NodeJS Stream 二:什么是 Stream

    对于大部分有后端经验的的同学来说 Stream 对象是个再合理而常见的对象,但对于前端同学 Stream 并不是那么理所当然,github 上甚至有一篇 9000 多 Star 的文章介绍到底什么是 ...

随机推荐

  1. The operator == is undefined for the argument type(s) int, null

    package cn.edu.shu.web.test; public class TestInteger { public static void main(String[] args) { /** ...

  2. fatjar eclipse4.4 java项目的jar包一起打包 net.sf.fjep.fatjar_0.0.32.jar

    1.下载net.sf.fjep.fatjar_0.0.32.jar  http://files.cnblogs.com/files/milanmi/net.sf.fjep.fatjar_0.0.32. ...

  3. SQL点滴13—收集SQLServer线程等待信息

    原文:SQL点滴13-收集SQLServer线程等待信息 要知道线程等待时间是制约SQL Server效率的重要原因,这一个随笔中将学习怎样收集SQL Server中的线程等待时间,类型等信息,这些信 ...

  4. SQL点滴9—SQL Server中的事务处理以及SSIS中的内建事务

    原文:SQL点滴9-SQL Server中的事务处理以及SSIS中的内建事务 我们可以把SSIS中的整个package包含在一个事务中,但是如果在package的执行过程中有一个表需要锁定应该怎么处理 ...

  5. HDU 2079-课程时间(生成函数)

    课程时间(标题已被修改,注意阅读题) Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Other ...

  6. sql简单实用的统计汇总案例参考

    USE [PM]GO/****** 对象:  StoredProcedure [dbo].[LfangSatstics]    脚本日期: 08/24/2013 10:57:48 ******/SET ...

  7. 为ASP.NET MVC应用程序实现继承

    为ASP.NET MVC应用程序实现继承 这是微软官方教程Getting Started with Entity Framework 6 Code First using MVC 5 系列的翻译,这里 ...

  8. 关于PHP 缓冲区

    最权威的资料:http://php.net/manual/en/function.flush.php 里面有全世界的开发者的留言.常见问题都有讨论. 再说一下PHP 缓冲区相关的. web服务器 如 ...

  9. MS SQL优化

    数据库优化实践[MS SQL优化开篇]   数据库定义: 数据库是依照某种数据模型组织起来并存在二级存储器中的数据集合,此集合具有尽可能不重复,以最优方式为特定组织提供多种应用服务,其数据结构独立于应 ...

  10. 2013.7.19 STL库的学习

    STL提供了一组表示容器,迭代器,函数对象和算法的模板. 容器是一个与数组类似的单元,可以存储若干个值.容器是同质的,即存储的值的类型一样. 算法是完成特定任务的处方. 迭代器能够用来遍历容器的对象, ...