Node.js中的缓冲与流模块详细介绍

缓冲(buffer)模块

js起初就是为浏览器而设计的,所以能很好的处理unicode编码的字符串,但不能很好的处理二进制数据。这是Node.js的一个问题,因为Node.js旨在网络上发送和接收经常是以二进制格式传输的数据。比如:

- 通过TCP连接发送和接收数据;
 - 从图像或者压缩文件读取二进制数据;
 - 从文件系统读写数据;
 - 处理来自网络的二进制数据流

而Buffer模块为Node.js带来了一种存储原始数据的方法,于是可以再js的上下文中使用二进制数据。每当需要在Node.js中处理I/O操作中移动的数据时,就有可能使用Buffer模块。

类:Buffer

Buffer 类是一个全局变量类型,用来直接处理2进制数据的。 它能够使用多种方式构建。

原始数据保存在 Buffer 类的实例中。一个 Buffer 实例类似于一个整数数组

1.new Buffer(size):分配一个新的 buffer 大小是 size 的8位字节.
2.new Buffer(array):分配一个新的 buffer 使用一个8位字节 array 数组.
3.new Buffer(str, [encoding]):encoding String类型 - 使用什么编码方式,参数可选.

4.类方法: Buffer.isEncoding(encoding):如果给定的编码 encoding 是有效的,返回 true,否则返回 false。
5.类方法: Buffer.isBuffer(obj):测试这个 obj 是否是一个 Buffer. 返回Boolean
6.类方法: Buffer.concat(list, [totalLength]):list {Array}数组类型,Buffer数组,用于被连接。totalLength {Number}类型 上述Buffer数组的所有Buffer的总大小。
除了可以读取文件得到Buffer的实例外,还能够直接构造,例如:

代码如下:

var bin = new Buffer([ 0x48, 0x65, 0x6c, 0x6c, 0x6c ]);

Buffer与字符串类似,除了可以用.length属性得到字节长度外,还可以用[index]方式读取指定位置的字节,例如:

代码如下:

bin[0]; // => 0x48;

Buffer与字符串能够互相转化,例如可以使用指定编码将二进制数据转化为字符串:

代码如下:

var str = bin.toString('utf-8'); // => "hello"

.slice方法不是返回一个新的Buffer,而更像是返回了指向原Buffer中间的某个位置的指针,如下所示。

代码如下:

1.[ 0x48, 0x65, 0x6c, 0x6c, 0x6c ]
2.    ^           ^
3.    |           |
4.   bin     bin.slice(2)

写入缓冲区


代码如下:

var buffer = new Buffer(8);//创建一个分配了8个字节内存的缓冲区
console.log(buffer.write('a','utf8'));//输出1

这会将字符"a"写入缓冲区,node返回经过编码以后写入缓冲区的字节数量,这里的字母a的utf-8编码占用1个字节。

复制缓冲区

Node.js提供了一个将Buffer对象整体内容复制到另一个Buffer对象中的方法。我们只能在已经存在的Buffer对象之间复制,所以必须创建它们。

代码如下:

buffer.copy(bufferToCopyTo)

其中,bufferToCopyTo是要复制的目标Buffer对象。如下示例:

代码如下:

var buffer1 = new Buffer(8);
buffer1.write('nice to meet u','utf8');
var buffer2 = new Buffer(8);
buffer1.copy(buffer2);
console.log(buffer2.toString());//nice to meet u

流模块

在UNIX类型的操作系统中,流是个标准的概念。有如下三个主要的流:

1.标准输入
2.标准输出
3.标准错误

可读流

如果说,缓冲区是Node.js处理原始数据的方式的话,那么流通常是Node.js移动数据的方式。Node.js中的流是可读的或者可写的。Node.js中许多模块都使用了流,包括HTTP和文件系统。

假设我们创建一个classmates.txt的文件,并从中读入姓名清单,以便使用这些数据。由于数据是流,这就意味着完成文件读取之前,从收到最初几个字节开始,就可以对数据动作,这是Node.js中的一个常见模式:

代码如下:

var fs = require('fs');
var stream = fs.ReadStream('classmates.txt');
stream.setEncoding('utf8');
stream.on('data', function (chunk) {
    console.log('read some data')
});
stream.on('close', function () {
    console.log('all the data is read')
});

在以上示例中,在收到新数据时触发事件数据。当文件读取完成后触发关闭事件。

可写流

显然,我们也可以创建可写流以便写数据。这意味着,只要一段简单的脚本,就可以使用流读入文件然后写入另一个文件:

代码如下:

var fs = require('fs');
var readableStream = fs.ReadStream('classmates.txt');
var writableStream = fs.writeStream('names.txt');
readableStream.setEncoding('utf8');
readableStream.on('data', function (chunk) {
    writableStream.write(chunk);
});
readableStream.on('close', function () {
    writableStream.end();
});

现在,当接收到数据事件时,数据会被写入可写流中。

readable.setEncoding(encoding):返回: this

readable.resume():同上。该方法让可读流继续触发 data 事件。

readable.pause():同上。该方法会使一个处于流动模式的流停止触发 data 事件,切换到非流动模式,并让后续可用数据留在内部缓冲区中。
类: stream.Writable

Writable(可写)流接口是对您正在写入数据至一个目标的抽象。

1.writable.write(chunk, [encoding], [callback]):

chunk {String | Buffer} 要写入的数据
encoding {String} 编码,假如 chunk 是一个字符串
callback {Function} 数据块写入后的回调
返回: {Boolean} 如果数据已被全部处理则 true。

该方法向底层系统写入数据,并在数据被处理完毕后调用所给的回调。

2.writable.cork():强行滞留所有写入。

滞留的数据会在 .uncork() 或 .end() 调用时被写入。

3.writable.end([chunk], [encoding], [callback])

chunk {String | Buffer} 可选,要写入的数据
encoding {String} 编码,假如 chunk 是一个字符串
callback {Function} 可选,流结束后的回调
在调用 end() 后调用 write() 会产生错误。

代码如下:

// 写入 'hello, ' 然后以 'world!' 结束
http.createServer(function (req, res) {
  res.write('hello, ');
  res.end('world!');
  // 现在不允许继续写入了
});

(0)

相关推荐

  • 详解Node.js串行化流程控制

    串行任务:需要一个接着一个坐的任务叫做串行任务. 可以使用回调的方式让几个异步任务按顺序执行,但如果任务过多,必须组织一下,否则过多的回调嵌套会把代码搞得很乱. 为了用串行化流程控制让几个异步任务按顺序执行,需要先把这些任务按预期的执行顺序放到一个数组中,这个数组将起到队列的作用:完成一个任务后按顺序从数组中取出下一个. 数组中的每个任务都是一个函数.任务完成后应该调用一个处理器函数,告诉它错误状态和结果. 为了演示如何实现串行化流程控制,我们准备做个小程序,让它从一个随机选择的RSS预定源中获

  • Node.js中流(stream)的使用方法示例

    前言 本文主要给大家介绍了关于Node.js 流(stream)的使用方法,分享出来供大家参考学习,下面话不多说,来一起看看详细的介绍: 流是基于事件的API,用于管理和处理数据,而且有不错的效率.借助事件和非阻塞I/O库,流模块允许在其可用的时候动态处理,在其不需要的时候释放掉. 使用流的好处 举一个读取文件的例子: 使用fs.readFileSync同步读取一个文件,程序会被阻塞,所有的数据都会被读取到内存中. 换用fs.readFile读取文件,程序不会被阻塞,但是所有的数据依旧会被一次性

  • 用NODE.JS中的流编写工具是要注意的事项

    Node.js中的流十分强大,它对处理潜在的大文件提供了支持,也抽象了一些场景下的数据处理和传递.正因为它如此好用,所以在实战中我们常常基于它来编写一些工具 函数/库 ,但往往又由于自己对流的某些特性的疏忽,导致写出的 函数/库 在一些情况会达不到想要的效果,或者埋下一些隐藏的地雷.本文将会提供两个在编写基于流的工具时,私以为有些用的两个tips. 一,警惕EVENTEMITTER内存泄露 在一个可能被多次调用的函数中,如果需要给流添加事件监听器来执行某些操作.那么则需要警惕添加监听器而导致的内

  • 深入nodejs中流(stream)的理解

    nodejs的fs模块并没有提供一个copy的方法,但我们可以很容易的实现一个,比如: var source = fs.readFileSync('/path/to/source', {encoding: 'utf8'}); fs.writeFileSync('/path/to/dest', source); 这种方式是把文件内容全部读入内存,然后再写入文件,对于小型的文本文件,这没有多大问题,比如grunt-file-copy就是这样实现的.但是对于体积较大的二进制文件,比如音频.视频文件,动

  • Nodejs Stream 数据流使用手册

    1.介绍 本文介绍了使用 node.js streams 开发程序的基本方法. <code class="hljs mizar">"We should have some ways of connecting programs like garden hose--screw in another segment when it becomes necessary to massage data in another way. This is the way of

  • Node.js中的缓冲与流模块详细介绍

    缓冲(buffer)模块 js起初就是为浏览器而设计的,所以能很好的处理unicode编码的字符串,但不能很好的处理二进制数据.这是Node.js的一个问题,因为Node.js旨在网络上发送和接收经常是以二进制格式传输的数据.比如: - 通过TCP连接发送和接收数据:  - 从图像或者压缩文件读取二进制数据:  - 从文件系统读写数据:  - 处理来自网络的二进制数据流 而Buffer模块为Node.js带来了一种存储原始数据的方法,于是可以再js的上下文中使用二进制数据.每当需要在Node.j

  • Node.js 中常用内置模块(path 路径模块)

    目录 前言 路径拼接:join方法 获取文件名:basename方法 获取文件扩展名:extname方法 结语 前言 进行服务端开发,少不了对各种路径的处理,之前我们是简单粗暴的使用字符串的方法来对路径进行拼接或截取等操作. Node.js 官方为我们提供了一个专门用来处理路径的模块:path模块,这个模块提供了一系列的方法和属性,用来满足用户对路径的处理需求. 路径拼接:join方法 path模块中有一个join方法,能够非常智能的进行路径拼接: 使用path.join()方法,可以把多个路径

  • node.js中RPC(远程过程调用)的实现原理介绍

    刚接触到RPC(远程过程调用),就是可以在本地调用远程机子上的程序的方法,看到一个简单的nodejs实现,用来学习RPC的原理很不错:nodejs light_rpc 使用示例: 复制代码 代码如下: //服务端 var light_rpc = require('./index.js'); var port = 5556; var rpc = new light_rpc({     combine: function(a, b, callback){         callback(a + b

  • 详解通过源码解析Node.js中cluster模块的主要功能实现

    众所周知,Node.js中的JavaScript代码执行在单线程中,非常脆弱,一旦出现了未捕获的异常,那么整个应用就会崩溃.这在许多场景下,尤其是web应用中,是无法忍受的.通常的解决方案,便是使用Node.js中自带的cluster模块,以master-worker模式启动多个应用实例.然而大家在享受cluster模块带来的福祉的同时,不少人也开始好奇: 为什么我的应用代码中明明有app.listen(port);,但cluter模块在多次fork这份代码时,却没有报端口已被占用? Maste

  • node.js中path路径模块的使用方法实例分析

    本文实例讲述了node.js中path路径模块的使用方法.分享给大家供大家参考,具体如下: path模块是node.js中处理路径的核心模块.可以很方便的处理关于文件路径的问题. join() 将多个参数值合并成一个路径 const path = require('path'); console.log(path.join('./a', 'b', 'c')); basename() 获取路径中的文件名 const path = require('path'); //获取文件名,包含扩展名 con

  • node.js中module模块的功能理解与用法实例分析

    本文实例讲述了node.js中module模块的功能理解与用法.分享给大家供大家参考,具体如下: node.js中使用CommonJS规范实现模块功能,一个单独的文件就是一个单独的模块.通过require方法实现模块间的依赖管理. 通过require加载模块,是同步操作. 加载流程如下: 1.找到需要加载的模块文件. 2.判断是否缓存过,如果没有,则读取模块文件的内容. 3.把读取到的内容,封装在一个函数里运行. (function (exports, require, module, __fi

  • 详解Node.js中的模块化方法

    目录 一.模块化的基本概念 1.什么是模块化 2.模块化规范 二.Node.js 中的模块化 1.Node.js 中的模块化分类 2.加载模块 3.向外共享模块作用域中的成员 4.Node.js 中的模块化规范 (1)什么是CommonJS模块规范 (2)CommonJS 模块化规范 (3)每个导出的模块都有一个moudle对象,该对象包含的属性有: 三.npm 与 包 1.包的概念 2.包的安装与卸载 3.包管理配置文件 总结 一.模块化的基本概念 1.什么是模块化 模块化是指解决一个复杂问题

  • Node.js中的child_process模块详解

    前言 本文主要给大家介绍了关于Node.js中child_process模块的相关内容,在介绍child_process模块之前,先来看一个例子. const http = require('http'); const longComputation = () => { let sum = 0; for (let i = 0; i < 1e10; i++) { sum += i; }; return sum; }; const server = http.createServer(); ser

  • Node.js中你不可不精的Stream(流)

    一.什么是Stream(流) 流(stream)在 Node.js 中是处理流数据的抽象接口(abstract interface). stream 模块提供了基础的API.使用这些API可以很容易地来构建实现流接口的对象.例如, HTTP 请求 和 process.stdout 就都是流的实例. 流可以是可读的.可写的,或是可读写的.注意,所有的流都是 EventEmitter 的实例. 二.流的类型 Node.js 中有四种基本的流类型: Readable - 可读的流 (例如 fs.cre

  • node.js中process进程的概念和child_process子进程模块的使用方法示例

    本文实例讲述了node.js中process进程的概念和child_process子进程模块的使用方法.分享给大家供大家参考,具体如下: 进程,你可以把它理解成一个正在运行的程序.node.js中每个应用程序都是进程类的实例对象. node.js中有一个 process 全局对象,通过它我们可以获取,运行该程序的用户,环境变量等信息. 一.process 对象 console.log('可执行文件绝对路径', process.execPath); console.log('版本号', proce

随机推荐