Node之IO

作者: 人失格 | 来源:发表于2017-09-07 20:49 被阅读41次

Buffer

Buffer的构成

Buffer对象类似数组,它的元素位16进制的两位数,即0到255的数值。主要是用来存储二进制的数据

const buf = Buffer.from('Hello world')

初始化Buffer会随机的填充了0到255的随机值

var buffer = new Buffer(100);
buffer[20] = -100;

console.log(buffer[20]) // 如果存储的数字小于0或者大于255则直接加值256知道值位于0到255之间

Buffer的底层分配

Node从c++层面申请内存,在JS层面用来分配内存的策略,Buffer在C++申请内存主要是8K。

Buffer的转换

目前Buffer的对象是可以直接与字符串进行互相转换,目前支持的字符串编码类型有

  • ASCII

  • UTF-8

  • UTF-16

  • Base64

  • Binary

  • Hex

    目前官方暂时不支持汉字编码GBK之类,如果有类似的汉字编码需求需要调用第三方库的支持。

Buffer的乱码现象

因为Buffer对象只要是用于二进制与字符串的转换,一旦设计编码 解码就会出现所谓的乱码现象,特别是出现在汉字编码问题。

var rs = fs.createReadStream('buffer.txt',{
  highWaterMark:11
});

var data = '';
rs.on('data',(thunk)=>{
  data +=thunk; // data.toString() += thunk.toString()
})

rs.on('end',()=>{
  console.log(data);
})

在Options上选择了highWaterMark,主要是影响操作系统读取文件的字节块,目前是按照11字节读取,因为汉字在UTF-8中编码只要是三个字节,所以在读取汉字的时候可能会出现两个字节导致无法编码,出现所谓的乱码现象。

乱码解决方案

  • stream.setEncoding('utf-8') 这样当stream读取到中文汉字需要解码的时候 底层的string_decoder 则会收集完整的字节然后解码显示汉字
  • 通过将stream中的数据接受完整数据后,然后指定编码符来统一解码。

Stream

Node.js中有四种基本的流类型:

  • Readable 可读的流(例如 fs.createReadStream())
  • Writable 可写的流 (例如 fs.createWriteStream())
  • Duplex 可读写的流 ( 例如 net.Socket)
  • Transform 在读写过程中科院修改和变换数据的Duplex流

缓冲

Writable和Readable流都会将数据存储到内部的缓存中。这些缓存可以通过相应的writable._writableState.getBuffer()或者readable._readableState.buffer来获取。 缓存的大小取决流构造函数的highWaterMark选项。对于普通的流, highWaterMark选项指定了总共的字节数。对于工作在对象模式的流,highWaterMark指定了对象的总数。

  • 当可读流实现调用了stream.push(chunk)方法,数据被放到了缓存中,如果流的消费者没有调用stream.read()方法,这些数据会始终存在内部队列,直到被消费。
  • 可写流通过反复调用writable.write(chunk)方法将数据放到缓存。当内部可写入缓存的总大小小于highWaterMark指定的阀值,调用writable.write()将返回true.
  • streamAPI的关键方法在于stream.pipe()方法,就是限制缓存数据大小,以达到可接受的程度。这样,对于读写速度不匹配的源头和目标。

可写流

Write Streams 是destination的一种抽象,这种destination允许数据写入

Writable的例子包括了

  • HTTP request, on the client
  • HTTP response, on the server
  • fs write streams
  • lib streams
  • crypto streams
  • TCP sockets
  • child process stdin

Writeable流暴露了一些方法 比如write() end() pipe()方法

Writable类的事件和方法

  • close事件 底层资源关闭后触发 close事件触发后,该流将不会再触发任何事件
  • drain 事件 当stream.write(chunk)方法返回false 出发 此时才能继续让缓冲区写入数据
  • error事件 stream写入数据出错
  • finish 事件 stream.end()方法
  • pipe 事件 输出到目标可写入流的源流 stream.pipe() 方法
  • writable.cork() 强制将所有写入数据源都放入内存中的缓冲区
  • writable.end(chunk, encoding, callback)
  • writable.setDefaultEncoding
  • writable.write(chunk,encoding,callback)
  • writable.destroy(error)

可读流

Readable的例子

  • HTTP response, on the client
  • HTTP request , on the server
  • fs read streams
  • zlib streams
  • crypto streams
  • TCP sockets
  • child process stdin

可读流的时间和方法

  • close事件
  • data事件
  • end事件
  • error事件
  • readable.pause()
  • readable.pipe()
  • readable.unpipe()
  • readable.setEncoding(encoding)
  • readable.destory(error)

两种模式

可读流事实上工作在下面两种模式之一: flowing 和paused

在flowing模式下,可读流自动从系统底层读取数据,并通过EventEmitter接口的事件尽快将数据提供给应用

在paused模式下,必须显示调用stream,read()方法来从流中读取数据片段

所有初始工作位paused的Readable流,可以通过下面三种途径切换到flowing模式:

  • 监听了'data'事件
  • 调用了stream.resume()方法
  • 调用了stream.pipe()方法将数据发送Writable

从Flowing模式切换到paused模式

  • 如果存在了管道目标,可以通过取消'data'事件箭筒,并调用stream.unpipe()方法移除所有管道目标来实现
  • 如果不存在管道目标,直接调用stream.pause()方法来实现

三种状态

任意可读流应确切处于下面三种状态:

  • readable._readableState.flowing = null

    由于不存在数据消费者,可读流将不会产生数据

  • readable._readableState.flowing = false

    调用 readable.pause() 方法, readable.unpipe() 方法, 或者接收 “背压”(back pressure), 将导致 readable._readableState.flowing 值变为 false。 这将暂停事件流,但 不会 暂停数据生成。

  • readable._readableState.flowing = true

    当stream监听了 'data'事件 调用了pipe方法,或者调用readable.resume()方法

相关文章

  • Node之IO

    Buffer Buffer的构成 Buffer对象类似数组,它的元素位16进制的两位数,即0到255的数值。主要是...

  • Node基础

    Node基础 为什么学习Node? IO优势对于文件读写,Node采用的是非阻塞IO传统IO在读写文件的时候CPU...

  • node-serialport

    https://node-serialport.github.io/node-serialport/Abstrac...

  • 前端进阶全栈-Node的异步IO

    本文力图详尽解释node的异步IO: 异步IO的产生背景 Node中的异步IO具体的实现 非I/O的异步API 一...

  • node环境搭建

    一、node.js的发展IO.JS和node.js是差不多的,io.js是社区产物,不是官方的东西,io.js有很...

  • node-socket.io

    node.js+socket.io Demo init 目录结构 node_modules publiccssst...

  • 基于Node.js、socket.io实现websocket聊天

    [TOC] Node.js与NPM 使用Socket.io需要安装Node.js与NPM(node package...

  • 发现一个深入讲解nodejs的网址

    https://yjhjstz.gitbooks.io/deep-into-node/

  • 初识node

    Node 基础 浏览器工作原理(Node优势):事件驱动(事件轮询)和非阻塞IO处理(异步IO)传统服务器是同步I...

  • node.js学习

    一.node知识 1.回调函数,即异步IO的node处理方式:时间循环,观察者,请求对象,io线程。 先在线程池处...

网友评论

    本文标题:Node之IO

    本文链接:https://www.haomeiwen.com/subject/dblwjxtx.html