Maison  >  Article  >  interface Web  >  Explication détaillée de l'utilisation du tampon Node.js

Explication détaillée de l'utilisation du tampon Node.js

php中世界最好的语言
php中世界最好的语言original
2018-05-28 15:40:061883parcourir

Cette fois, je vous apporte une explication détaillée de l'utilisation de Node.js Buffer, et quelles sont les précautions lors de l'utilisation de Node.js Buffer. Ce qui suit est un cas pratique. , jetons un coup d'oeil.

Qu'est-ce que Buffer ?

Buffer existe en tant qu'objet global et peut être utilisé sans introduire de module. Vous ne devez pas l'ignorer.

On peut comprendre que Buffer est une zone ouverte en mémoire pour stocker des données binaires. Le tampon ouvre la mémoire hors tas.

Quels sont les scénarios d'application de Buffer ?

Flow

Comment comprendre le flow ? Le flux est une collection de données (similaire aux données, String), mais les données du flux ne peuvent pas être obtenues en une seule fois et les données ne seront pas toutes chargées dans la mémoire. Par conséquent, le flux est. très approprié pour le traitement du Big Data et les retours intermittents. La source externe du chunk. La vitesse entre les producteurs de flux et les consommateurs est généralement incohérente, des tampons sont donc nécessaires pour stocker temporairement certaines données. La taille du tampon est spécifiée par le paramètre highWaterMark, qui est de 16 Ko par défaut.

Stockage de données qui nécessitent beaucoup de mémoire

L'espace mémoire occupé par l'objet Buffer n'est pas compté dans la limite d'espace mémoire du processus Node.js, il peut donc être utilisé pour le stockage de gros objets, mais la taille de l'objet est toujours limitée. Généralement, un système 32 bits équivaut à environ 1G et un système 64 bits à environ 2G.

Comment créer un Buffer

En plus du flux créant automatiquement un Buffer implicitement, vous pouvez également créer un Buffer manuellement comme suit :

Les données stockées dans Buffer ont été déterminées

Buffer.from(obj) // Les types pris en charge par obj string, buffer, arrayBuffer, array ou array- like object

Remarque : Buffer.from ne prend pas en charge la transmission de nombres, comme indiqué ci-dessous :

Buffer.from(1234);
buffer.js:208
  throw new errors.TypeError(
  ^
TypeError [ERR_INVALID_ARG_TYPE]: The "value" argument must not be of type number. Received type number
  at Function.from (buffer.js:208:11)
  ...

Si vous souhaitez transmettre des nombres, vous pouvez transmettre un tableau :

const buf = Buffer.from([1, 2, 3, 4]);
console.log(buf); // <Buffer 01 02 03 04>

Mais ceci Il y a un problème avec cette méthode. Lorsque différentes valeurs sont stockées, les données binaires enregistrées dans le tampon seront les mêmes, comme indiqué ci-dessous :

const buf2 = Buffer.from([127, -1]);
console.log(buf2);   // <Buffer 7f ff>
const buf3 = Buffer.from([127, 255]);
console.log(buf3);  // <Buffer 7f ff>
console.log(buf3.equals(buf2)); // true

Lorsqu'un ensemble de nombres à enregistrer se situent tous entre 0 et 255 (readUInt8 pour lire) cette plage, ou tous se situent dans la plage de -128 à 127 (readInt8 pour lire) cette plage, alors il n'y a pas de problème, sinon c'est Il est fortement déconseillé d'utiliser Buffer.from pour enregistrer un ensemble de nombres. Parce que différentes méthodes doivent être appelées lors de la lecture de différents nombres.

Les données de stockage du tampon ne sont pas déterminées

Buffer.alloc, Buffer.allocUnsafe, Buffer.allocUnsafeSlow

Buffer.alloc will Remplit la mémoire allouée avec 0 valeurs, donc c'est plus lent que les deux derniers, mais c'est aussi plus sûr. Bien sûr, vous pouvez également utiliser l'indicateur --zero-fill-buffers pour que allocUnsafe et allocUnsafeSlow se remplissent de valeurs nulles après avoir alloué de la mémoire.

node --zero-fill-buffers index.js

Lorsque l'espace alloué est inférieur à 4 Ko, allocUnsafe découpera directement l'espace du tampon précédemment pré-alloué, de sorte que la vitesse est plus rapide que allocUnsafeSlow lorsque l'espace alloué est supérieur ou égal à. 4 Ko, il n'y a aucune différence de vitesse entre les deux.

// 分配空间等于4KB
function createBuffer(fn, size) {
 console.time('buf-' + fn);
 for (var i = 0; i < 100000; i++) {
  Buffer[fn](size);
 }
 console.timeEnd(&#39;buf-&#39; + fn);
}
createBuffer(&#39;alloc&#39;, 4096);
createBuffer(&#39;allocUnsafe&#39;, 4096);
createBuffer(&#39;allocUnsafeSlow&#39;, 4096);
// 输出
buf-alloc:      294.002ms
buf-allocUnsafe:   224.072ms
buf-allocUnsafeSlow: 209.22ms
function createBuffer(fn, size) {
 console.time(&#39;buf-&#39; + fn);
 for (var i = 0; i < 100000; i++) {
  Buffer[fn](size);
 }
 console.timeEnd(&#39;buf-&#39; + fn);
}
createBuffer(&#39;alloc&#39;, 4095);
createBuffer(&#39;allocUnsafe&#39;, 4095);
createBuffer(&#39;allocUnsafeSlow&#39;, 4095);
// 输出
buf-alloc:      296.965ms
buf-allocUnsafe:   135.877ms
buf-allocUnsafeSlow: 205.225ms

Une chose à retenir : la nouvelle méthode Buffer(xxxx) n'est plus recommandée

Utiliser Buffer

buffer to string

const buf = Buffer.from(&#39;test&#39;);
console.log(buf.toString(&#39;utf8&#39;));         // test
console.log(buf.toString(&#39;utf8&#39;, 0, 2));      // te

buffer to json

const buf = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5]);
console.log(buf.toJSON());  // { type: &#39;Buffer&#39;, data: [ 1, 2, 3, 4, 5 ] }

buffer clipping, return after clipping Le le nouveau tampon pointe vers la même mémoire que le tampon d'origine

buf.slice([start[, end]])
  1. début position de départ

  2. fin position de fin (ne contient pas )

Exemple :

var buf1 = Buffer.from(&#39;test&#39;);
var buf2 = buf1.slice(1, 3).fill(&#39;xx&#39;);
console.log("buf2 content: " + buf2.toString()); // xx
console.log("buf1 content: " + buf1.toString()); // txxt

copie du tampon, le tampon est différent du tableau, la longueur du tampon ne changera pas une fois déterminée, donc lorsque la source copiée le tampon est plus grand que Lorsque le tampon cible est grand, seule une partie de la valeur

buf.copy(target[, targetStart[, sourceStart[, sourceEnd]]])

sera copiée Exemple :

var buf1 = Buffer.from(&#39;abcdefghijkl&#39;);
var buf2 = Buffer.from(&#39;ABCDEF&#39;);
buf1.copy(buf2, 1);
console.log(buf2.toString()); //Abcdef

Jugement d'égalité du tampon, la comparaison est. la valeur binaire

buf.equals(otherBuffer)

Exemple :

const buf1 = Buffer.from(&#39;ABC&#39;);
const buf2 = Buffer.from(&#39;414243&#39;, &#39;hex&#39;); 
console.log(buf1.equals(buf2));  // true

En plus des égaux, comparer peut également être utilisé pour déterminer s'ils sont égaux (lorsque le résultat est 0, ils sont égaux), mais la fonction principale de compare est de comparer dans le tri des instances de tampon de tableau.

Si le tampon contient une valeur spécifique

buf.includes(value[, byteOffset][, encoding])
buf.indexOf(value[, byteOffset][, encoding])

示例:

const buf = Buffer.from(&#39;this is a buffer&#39;);
console.log(buf.includes(&#39;this&#39;)); // true
console.log(buf.indexOf(&#39;this&#39;)); // 0

写入读取数值

写入方法:

位数固定且超过1个字节的: write{Double| Float | Int16 | Int32| UInt16 | UInt32 }{BE|LE}(value, offset)

位数不固定的: write{Int | UInt}{BE | LE}(value, offset, bytelength) //此方法提供了更灵活的位数表示数据(比如3位、5位)

位数固定是1个字节的: write{Int8 | Unit8}(value, offset)

读取方法:

位数固定且超过1个字节的: read{Double| Float | Int16 | Int32 | UInt16 | UInt32 }{BE|LE}(offset)

位数不固定的: read{Int | UInt}{BE | LE}(offset, byteLength)

位数固定是1个字节的: read{Int8 | Unit8}(offset)

Double、Float、Int16、Int32、UInt16、UInt32既确定了表征数字的位数,也确定了是否包含负数,因此定义了不同的数据范围。同时由于表征数字的位数都超过8位,无法用一个字节来表示,因此就涉及到了计算机的字节序区分(大端字节序与小端字节序)

关于大端小端的区别可以这么理解:数值的高位在buffer的起始位置的是大端,数值的低位buffer的起始位置则是小端

const buf = Buffer.allocUnsafe(2);
buf.writeInt16BE(256, 0) 
console.log(buf);      // <Buffer 01 00> 
buf.writeInt16LE(256, 0)
console.log(buf);      // <Buffer 00 01>

http://tools.jb51.net/transcoding/hexconvert这里可以查看数值的不同进制之间的转换,如果是大端的话,则直接按顺序(0100)拼接16进制即可,如果是小端则需要调换一下顺序才是正确的表示方式。

buffer合并

Buffer.concat(list[, totalLength]) //totalLength不是必须的,如果不提供的话会为了计算totalLength会多一次遍历

const buf1 = Buffer.from('this is');
const buf2 = Buffer.from(' funny');
console.log(Buffer.concat([buf1, buf2], buf1.length + buf2.length));
// <Buffer 74 68 69 73 20 69 73 20 66 75 6e 6e 79>

清空buffer

清空buffer数据最快的办法是buffer.fill(0)

buffer模块与Buffer的关系

Buffer是全局global上的一个引用,指向的其实是buffer.Buffer

 const buffer = require('buffer');
 console.log(buffer.Buffer === Buffer); //true

buffer模块上还有其他一些属性和方法

const buffer = require('buffer');
console.log(buffer);
{ Buffer:
  { [Function: Buffer]
   poolSize: 8192,
   from: [Function: from],
   alloc: [Function: alloc],
   allocUnsafe: [Function: allocUnsafe],
   allocUnsafeSlow: [Function: allocUnsafeSlow],
   isBuffer: [Function: isBuffer],
   compare: [Function: compare],
   isEncoding: [Function: isEncoding],
   concat: [Function: concat],
   byteLength: [Function: byteLength],
   [Symbol(node.isEncoding)]: [Function: isEncoding] },
 SlowBuffer: [Function: SlowBuffer],
 transcode: [Function: transcode],
 INSPECT_MAX_BYTES: 50,
 kMaxLength: 2147483647,
 kStringMaxLength: 1073741799,
 constants: { MAX_LENGTH: 2147483647, MAX_STRING_LENGTH: 1073741799 } }

上面的kMaxLength与MAX_LENGTH代表了新建buffer时内存大小的最大值,当超过限制值后就会报错

32为机器上是(2^30)-1(~1GB)

64位机器上是(2^31)-1(~2GB)

Buffer释放

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

如何搭建React全家桶环境

怎样使用JS实现调用本地摄像头

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn