六、Buffer缓冲区和Stream流

news2024/11/23 22:44:56

Buffer —— 缓冲区

        JavaScript 提供了大量对字符串的便捷操作,但没有读取或操作二进制数据流机制,而在Node.js中可以直接用Buffer类提供的构造函数创建Buffer实例,一个Buffer实例代表一个缓冲区,Buffer的缓冲区专门用于存放二进制数据,进行二进制字节流的读写、网络传输;数据在计算机中以二进制形式表示,那么需要用字符编码转换,比如非常熟悉的字符编码UTF-8,字符集和字符编码一般都是成对的,比如:GB2312,GBK,ASXII,IOS-8859-1 ... ,那么对Buffer有基本的了解之后,来使用一下Buffer:

创建Buffer

 Buffer.from()

        Buffer.from(value,...)方法申请一个被字符串值初始化的Buffer实例;

// from.js 返回一个被string初始化的新Buffer实例
const buff = Buffer.from('Hello');    
console.log(buff);

        Buffer的访问可以像数组一样;

console.log(buff[0]);    // H - 72

         buff.length —— 获取到 Buffer 长度;

        使用 for 遍历 buffer;

const buff = Buffer.from('Hello');
for(const item of buff){
    console.log(item);  // 72 101 108 108 111
}

          通过数组的方式修改Buffer 

const buff = Buffer.from('Hello');    
// H[72] e[101] l[108] l[108] o[111];
buff[1] = 111;
console.log(buff.toString());   // Hollo  

        write ——更改Buffer

const buff = Buffer.from('Hey');
buff.write('www');
console.log(buff.toString());    // www

Buffer.alloc() 

        Buffer.alloc(size[,fill [,encoding]]) 返回一个指定size字节空间大小的Buffer实例;size 指字节大小,fill 指设置新建Buffer初始值,省略则默为undefined,encoding默认为utf-8;

// alloc.js
const buff1 = Buffer.alloc(6);                   // size
const buff2 = Buffer.alloc(6,3);                 // size , fill
const buff3 = Buffer.alloc(6,'点赞','utf-8');    // size , fill , encoding
console.log( ... )

        fill 为undefined时,Buffer则用0填充;一个汉字3个字节,size超过12字节的内容会被截断;

// alloc.js
const buff1 = Buffer.alloc(12,'灵魂学者','utf-8');
const buff2 = Buffer.alloc(12,'灵魂学者感谢各位','utf-8');
console.log(buff1);
console.log(buff2);

         通过以上的两端Buffer可以看到第二段的Buffer与第一段Buffer一样,那么为了更加直观,将Buffer进行转为字符串的形式来看:

toString() —— 转字符串

console.log(buff1.toString());
console.log(buff2.toString());

write 

const buff = Buffer.alloc(4);
buff.write('lhxz');
console.log(buff.toString());    // lhxz

copy 

const buff1 = Buffer.alloc(4,'lhxz');
const buff2 = Buffer.alloc(4);
buff1.copy(buff2);
console.log(buff1.toString(),buff2.toString());


 Buffer.allocUnsafe()

        Buffer.allocUnsafe(size) 返回一个size字节大小的新的非0填充的Buffer,生产Buffer实例不被初始化,size是一个数字表示分配字节大小,size不是数字则会抛出TypeError错误。

// allocUnsafe.js文件
const buff1 = Buffer.allocUnsafe(12);
const buff2 = Buffer.allocUnsafe(12);
console.log(buff1);
console.log(buff2);

         每通过Buffer.allocUnsafe()执行的结果都不相同,因为该方法分配的空间是未重置的,会保留先前的垃圾信息;allocUnsafe的使用是很不安全的,但读取速率比alloc更快;一般使用Buffer.allocUnsafe() 创建Buffer之后要使用Buffer.fill(0) 将这个Buffer初始化为0;

const buff = Buffer.allocUnsafe(12);
buff.fill(0);

Buffer转为不同字符编码的字符串

const buff = Buffer.from('感谢有你');
console.log(buff);
console.log(buff.toString());
console.log(buff.toString('ascii'));
console.log(buff.toString('base64'));
console.log(buff.toString('utf-8'));


切片Buffer

const buff = Buffer.from('lhxz');
buff.slice(0).toString();       // lhxz
const slice1 = buff.slice(0,2);  // lh
const slice2 = buff.slice(2,4);  // xz
console.log(slice1.toString(),slice2.toString());

合并Buffer

        Buffer.concat(list[,totalLength]),返回一个合并了list中所有Buffer实例的新Buffer;

const buff1 = Buffer.concat([slice1,slice2]);
console.log(buff1);
console.log(buff1.toString());

toJSON() —— 返回JSON对象

const buff = Buffer.from('mp.csdn.net');
console.log(buff.toJSON());


Stream流

         通过之前的fs文件系统模块,如果对一个很大的数据文件进行网络读写传输的话,需要通过fs.readFile()读取文件 - fs.writeFile()写入文件,这个读写过程对整个文件的全部内容进行一次性完整读写,由于Buffer缓冲区的限制在1GB,超过就无法直接完成读写,所以Node.js对于大数据的读写就出现问题,随之出现的就是Stream流来解决!

        fs流是Node.js的抽象接口,fs流的最大作用就是读取大文件的过程,不会一次性的全读而是每次只读数据源的一个数据块,数据处理完后会进入垃圾回收机制!

        在Node.js中,文件流的类型有四种:1.Readable可读  2.Writeable可写  3.Duplex可读可写  4.Transform操作被写入,然后读出结果;

流的事件 —— 所有流对象都是事件发射器EventEmitter的实例
data 事件当有数据可读时触发
end事件没有更多的数据可读时触发
error事件在接收和写入过程中发生错误异常时触发
finish事件所有数据已被写入底层系统时触发

fs.createReadStream() —— 创建可读流

        fs.createReadStream(path[,options])可以来创建fs可读流,用于从流中读取数据;

// createReadStream.js文件

const fs = require('fs');
const path = require('path');

var data = '';
const readStream = fs.createReadStream(path.join(__dirname + '/read.txt'))
readStream.setEncoding('utf-8');
readStream.on('data',function(chunk){       // 有数据时触发
    data += chunk;
})

readStream.on('end',function(){             // 没有数据时触发
    console.log('该文件内容中无内容!')
})

readStream.on('error',function(err){
    console.log('出现异常:',err.stack);     // 打开文件出现异常时触发
})

console.log('程序执行完成!')

 /read.txt 能够正常读取,改为/reads.txt(无该文件),使其读取异常报错;


fs.createWriteStream() —— 创建可写流

        fs.createWriteStream(path[,options])可以来创建可写流,也称写入流;

// createWriteStream.js文件

const fs = require('fs');
const path = require('path');

var data = 'syan123将会写入到read.txt文件中';
const writeStream = fs.createWriteStream(path.join(__dirname + '/read.txt'));
writeStream.write(data,'utf-8');
writeStream.end();

// 数据处理 ——> finish,error
writeStream.on('finish',function(){
    console.log("写入完成!");
})
writeStream.on('error',function(err){
    console.log("出现异常:",err.stack);
})


 管道流 —— pipe()

        readable.pipe(destination[,options]),管道流是可读流的一种方法,通过用于从一个流中获取数据并将数据传递到另外一个流中,将可读流的信息通过管道方式写入可写流的一种数据写入方式;

// pipe.js文件
const fs = require('fs');
const path = require('path');

const readStream = fs.createReadStream(__dirname + '/input.txt');
const writeStream = fs.createWriteStream(__dirname + '/output.txt');

readStream.pipe(writeStream);
console.log('—— <complete> ——');


 链式流

        将输出流与另外一个流连接起来并创建多个流操作链的机制,这种流通常会用在管道流上能够对单个可读流上绑定多个可写流操作链;

1)可读流读取input.txt文件 ——  pipe() 进行压缩  ——  pipe() 进行写入流写入output.txt 文件

const fs = require('fs');
const path = require('path');
const zlib = require('zlib');    // zlib压缩文件模块

const inp = fs.createReadStream(path.join(__dirname+'/input.txt'));
const out = fs.createWriteStream(path.join(__dirname+'/input.txt.rar'));
inp.pipe(zlib.createGzip()).pipe(out);

console.log('File压缩完成!')

 

2)可读流读取压缩文件input.txt.rar —— pipe() 进行解压 —— pipe() 进行写入流写入out.txt 文件

const inp = fs.createReadStream(path.join(__dirname + '/input.txt.rar'));
const out = fs.createWriteStream(path.join(__dirname + '/out.txt'));

inp.pipe(zlib.createGunzip()).pipe(out);

console.log("File解压完成!")

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/108688.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

全球「数字游民」现状,有人已经72岁了

近年来&#xff0c;“数字游民”在国内越来越流行&#xff0c;特别是受疫情的影响&#xff0c;很多人对这种工作生活方式越来越喜欢&#xff0c;也越来越习惯&#xff0c;在此之前&#xff0c;当你告诉别人你是一名“数字游民”时&#xff0c;大家通常会认为你是没有工作的无业…

RocketMQ-双主双从集群+DashBorad搭建(云服务器)

文章目录一、理论垫基础1. NameServer 集群2. Producer集群3. Consumer集群4. Broker集群4.1 节点间数据同步 以及 消息的持久化4.2 Broker的集群模式4.2.1、单Master模式4.2.2、多Master模式4.2.3、多Master多Slave模式-异步复制4.2.4、多Master多Slave模式-同步双写最佳实践4…

APM32F103 RTC内部时钟源报警中断例程测试

APM32F103 RTC内部时钟源报警中断例程测试✨相关篇推荐《【开源电路】STM32F103VCT6开发板》&#x1f4cc;关篇《APM32F103 RTC内部时钟源秒中断例程测试》&#x1f4cc;本案例来源于官方的SDK固件包&#xff1a;https://www.geehy.com/support/apm32 &#x1f388;源码位置&am…

二极管:烧IC与我相干!

趁“羊”未到&#xff0c;还有心力接着上节继续讲。 话说&#xff0c;烧IC&#xff0c;不只本身IC烧&#xff0c;还火烧连营连带后端IC一并烧&#xff0c;为何呢&#xff01;&#xff1f; 那得回到过去&#xff0c;必须翻翻《硬件先生》中的《电源知识-DC-DC》&#xff0c;从D…

GPU与CPU的性能比较及影响因素

CPU的主要指标是主频和线程。 Intel&#xff1a;后缀F表示无核显&#xff0c;后缀K代表可以超频&#xff0c;H代表移动端&#xff1b;AMD&#xff1a;后缀G代表有核显&#xff0c;后缀X代表加强版&#xff0c;后缀XT代表超级加强版。 CPU 常见计算操作&#xff1a; 数据加载、…

4.0、Hibernate-延迟加载 2

4.0、Hibernate-延迟加载 2 消费者 和 订单 属于 一对多 的 关系&#xff0c;通过上一章节 3.0 的内容我们知道了可以通过设置 customer 来实现延迟加载&#xff0c;本章节来介绍一下如何设置 orders 去实现延迟加载&#xff1b; one-to-many 的 lazy 默认是 true 是开启的&…

%29 身份认证

1、Web 开发模式 &#xff08;1&#xff09;、基于服务器渲染的开发模式&#xff1a;服务器发送给客户端的 HTML 页面&#xff0c;是在服务器通过字符串的拼接&#xff0c;动态生成的&#xff08;企业级网站&#xff09; &#xff08;2&#xff09;、基于前后端分离的开发模式&…

登录过程(vuex存储token、token持久化)

登录过程(vuex存储数据) 点击登录按钮通过表单校验 this.$refs.loginForm.validate(valid > {if (valid) {//按钮动画加载,禁用 this.loading true// 调用vuex的action发送登录请求this.$store.dispatch(user/login, this.loginForm).then(() > {this.$router.push({ p…

内存分配函数(动态内存分配)详解

目录 &#x1f391;为什么要进行动态内存开辟&#xff1f; &#x1f391;malloc和free &#x1f3a0;malloc函数 &#x1f3a0;free函数 &#x1f3a0;malloc函数和free函数的实际应用 &#x1f391;calloc函数 &#x1f391;realloc函数 &#x1f3a0;realloc函数的使用示例 &…

通过脚手架vue-cli创建一个vue项目

我需要在vue-demo文件下新建vue项目 步骤一 ①在该文件夹下打开集成终端 输入创建命令 命令 vue create 项目名称 &#xff0c;注意不要使用驼峰命名法 如果是第一次配置&#xff0c;有面的提示&#xff0c;这里说你这样速度会很慢的&#xff0c;用不用镜像啊&#xff0c;这…

样品制备丨艾美捷硝酸盐/亚硝酸盐荧光法检测试剂盒

一氧化氮&#xff08;NO&#xff09;是由一氧化氮合酶&#xff08;NOS&#xff09;在生物系统中合成的。NOS是一种非常复杂的酶&#xff0c;作用于分子氧、精氨酸和NADPH&#xff0c;产生NO、瓜氨酸和NADP。这个过程需要五个额外的辅因子&#xff08;FMN、FAD、血红素、钙调素和…

制造业ERP管理系统在企业采购管理中的作用是什么?

对于任何一家企业&#xff0c;采购都是头等大事。企业的采购工作往往是决定了企业产品的交货速度、成本和质量&#xff0c;特别是在制造行业&#xff0c;采购成本甚至占比产品成本的60%以上&#xff0c;降低采购成本是提高企业竞争力的关键。因此&#xff0c;对于企业采购领域的…

Effective C++条款34:区分接口继承和实现继承

Effective C条款34&#xff1a;区分接口继承和实现继承&#xff08;Differentiate between inheritance of interface and inheritance of implementation&#xff09;条款34&#xff1a;区分接口继承和实现继承1、纯虚函数2、虚函数&#xff08;非纯&#xff09;2.1 将默认实现…

2022 IoTDB Summit:中国核电刘旭嘉《工业时序数据库 Apache IoTDB 在核电的应用实践》...

12 月 3 日、4日&#xff0c;2022 Apache IoTDB 物联网生态大会在线上圆满落幕。大会上发布 Apache IoTDB 的分布式 1.0 版本&#xff0c;并分享 Apache IoTDB 实现的数据管理技术与物联网场景实践案例&#xff0c;深入探讨了 Apache IoTDB 与物联网企业如何共建活跃生态&#…

middlebury立体匹配评估使用方法总结(三)——线上版教程

系列文章目录 middlebury立体匹配评估使用方法总结&#xff08;一&#xff09;——网站说明 middlebury立体匹配评估使用方法总结&#xff08;二&#xff09;——python版离线教程 middlebury立体匹配评估使用方法总结&#xff08;三&#xff09;——线上版教程 文章目录系列文…

TableLayout布局

表格布局-TableLayout 1.TableLayout简介 1.简介 表格的形式&#xff0c;整齐可以嵌套继承于线性布局2.行数如何确定&#xff1f; tableRow&#xff0c;来指定行数列数由最多的那个决定layout_column来指定具体的列数&#xff0c;从0开始2.TableLayout的常见属性 所有的都是从0…

VMware ESxi 服务器迁移【手动版】

VMware ESxi 迁移【手动版】 应用场景 两个不同环境下的服务器进行迁移 因为不能直接对拷&#xff0c;需要在中间机上转一下 才有了这么一出 第一步 搭建NFS 在中间机上安装NFS&#xff08;或者其他磁盘挂载方式&#xff09; 目的呢是把源服务器上的系统拷贝到中间机上&#x…

android入门之broadcast

1. 前言 广播Broadcast是android四大组件之一。是用来互相通信&#xff08;传递信息&#xff09;的一种机制。 通信包括&#xff1a; a) 组件间&#xff08;应用内&#xff09;通信 b) 进程间通信 2. 广播Brocast的基本使用方式 广播发送者&#xff1a;Acvitity、Service等…

pdf文档页码怎么添加?分享这几个pdf加页码方法给你

不管是还在校园里的学生&#xff0c;还是已经步入职场的小伙伴&#xff0c;都会遇到要对一些文档进行编辑处理&#xff0c;例如有时需要将word、excel、ppt等格式的文档与pdf文件进行相互转换&#xff0c;有时又需要对pdf文件进行编辑文档增加页眉页脚、拆分合并、加密解密等操…

基于Python+Echarts+Pandas 搭建一套图书分析大屏展示系统(附源码)

今天给大家分享的是基于 Flask、Echarts、Pandas 等实现的图书分析大屏展示系统。 项目亮点 采用 pandas、numpy 进行数据分析 基于 snownlp、jieba 进行情感分析 后端接口选用 RESTful 风格&#xff0c;构建 Swagger 文档 基于 Flask、Echarts 构建 Web 服务&#xff0c;采…