Node.js 全局对象Buffer对象流

Posted YuLong~W

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Node.js 全局对象Buffer对象流相关的知识,希望对你有一定的参考价值。

全局对象

全局属性

  • __filename 指向当前正在执行的脚本文件名
  • __dirname 指向当前运行的脚本所在的目录(路径)

全局对象

1、global对象:

表示 Node 所在的全局环境,类似于浏览器中的window对象。所有全局变量都是global对象的属性,如:console、process等。

在浏览器中全局对象是window,在Node中全局对象是global

Node中全局对象下有以下方法,可以在任何地方使用,global可以省略

方法说明
console.log()在控制台中输出
setTimeout()设置超时定时器
clearTimeout()清除超时时定时器
setInterval()设置间歇定时器
clearInterval()清除间歇定时器

2、console对象:

指向Node内置的console模块,提供命令行环境中的标准输入、标准输出功能。通常是写console.log()。

全局console实例对象:

console.log('hello world'); // 打印hello world到标准输出流
console.log('hello %s', 'world');// 打印hello world到标准输出流
console.error(new Error('错误信息')); //打印 [Error: 错误信息] 到标准错误流
const name = 'Robert';
console.warn(`Danger ${name}! Danger!`);// 打印Danger Robert! Danger!到标准错误流

Console类:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world'); // 打印hello world到out流
myConsole.log('hello %s', 'world'); //打印hello world到out流
myConsole.error(new Error('错误信息')); //打印 [Error: 错误信息] 到 err流
const name = 'Robert';
myConsole.warn(`Danger ${name}! Danger!`); //打印Danger Robert! Danger!到 err流

3、process:进程对象

process对象是 Node 的一个全局对象,提供当前 Node 进程的信息。它可以在脚本的任意位置使用,不必通过require命令加载。该对象部署了EventEmitter接口

process对象属性

属性描述
process.argv返回一个数组,成员是当前进程的所有命令行参数。
process.env返回一个对象,成员为当前Shell的环境变量。
process.installPrefix返回一个字符串,表示 Node 安装路径的前缀。
process.pid返回一个数字,表示当前进程的进程号。
process.platform返回一个字符串,表示当前的操作系统,比如Linux。
process.title返回一个字符串,默认值为node,可以自定义该值。
process.version返回一个字符串,表示当前使用的 Node 版本。

process.stdout:属性返回一个对象,表示标准输出。该对象的write方法等同于console.log,可用在标准输出向用户显示内容

process.stdout.write('Hello World');

process.stdin:返回一个对象,表示标准输入,利用该对象可以从标准输入终端向node程序输入数据

process.stdout.write('请输入数据:')
process.stdin.on('data',(data)=>{
     process.stdout.write("输入的数据是:"+data.toString().trim())
     process.exit(0) //结束进程
 })

stderr:指向标准错误

process对象方法

方法描述
process.on()监听事件
process.exit()退出当前进程
process.chdir()切换工作目录到指定目录
process.cwd()返回运行当前脚本的工作目录的路径
process.getgid()返回当前进程的组ID(数值)
process.getuid()返回当前进程的用户ID(数值)
process.nextTick()指定回调函数在当前执行栈的尾部、下一次Event Loop之前执行
process.setgid()指定当前进程的组,可以使用数字ID,也可以使用字符串ID
process.setuid()指定当前进程的用户,可以使用数字ID,也可以使用字符串ID

process.on()

process对象部署了EventEmitter接口,可以使用on方法监听各种事件,并指定回调函数

process支持的事件还有下面这些:

  • data事件:数据输出输入时触发
  • SIGINT事件:接收到系统信号SIGINT时触发,主要是用户按Ctrl + c时触发。
  • SIGTERM事件:系统发出进程终止信号SIGTERM时触发
  • exit事件:进程退出前触发

例如:进程退出时,显示一段日志

process.on("exit", code =>
  console.log("exiting with code: " + code))

注意: 此时回调函数只能执行同步操作,不能包含异步操作,因为执行完回调函数,进程就会退出,无法监听到回调函数的操作结果。

Buffer对象

  • Buffer对象是专门用于处理二进制数据的对象(接口),由Node原生创建,可以直接使用不需要导入
  • Buffer对象又称为缓冲区对象,它有一个构造函数,由构造函数创建的对象,v8引擎会为其分配一块内存
  • Buffer中存放的数据是0~255之间的整数值(即一个字节的数据)

Buffer实例对象用法

1、创建Buffer实例对象

  • (1)使用new运算符
    var 变量 = new Buffer([参数])
    
  • (2)使用from函数
    var 变量 = Buffer.from([参数])
    
  • (3)使用alloc函数
    var 变量 = Buffer.alloc(size,fill)
    

2、Buffer用于编码转换

  • Buffer实例一般用于表示编码字符的序列,如UTF-8、UCS2、Base64或十六进制编码的数据。

  • 在文件操作和网络操作中,如果没有显式声明编码格式,返回数据的默认类型为Buffer

  • 通过使用显式字符编码将Buffer实例与javascript字符串相互转换。

  • 在创建Buffer实例时指定存入字符串的字符编码

    const buf = Buffer.from('hello world', 'ascii');
    
  • 将Buffer实例转换成字符串的语法:buf.toString([encoding[, start[, end]]])

    const buf = Buffer.from('tést');
    console.log(buf.toString('hex'));// 输出结果: 74c3a97374
    console.log(buf.toString('utf8', 0, 3));//输出结果:té
    

3、Buffer转换为JSON对象

JSON(JavaScript Object Notation)对象:是前后端数据交换的常用格式,是以 key-value 的方式保存数据,由于体积小、创建方便、解析简单,所以被广泛使用。只要应用程序需要将结构化信息作为文本进行交换或存储,即可使用它

  • 使用buf.toJSON()方法将Buffer实例转换为JSON对象,适用于将二进制数据转换为JSON格式

    const buf = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5]);
    const json = JSON.stringify(buf);
    console.log(json);  // 输出:{"type":"Buffer","data":[1,2,3,4,5]}
    

4、Buffer实例基本操作

  • (1) 写入Buffer实例:使用 buf.write() 方法将字符串写入Buffer实例
    语法:buf.write(string[, offset[, length]][, encoding])

    const buf = Buffer.alloc(256);
    let len = buf.write('\\u00bd+\\u00bc=\\u00be',0); 
    console.log(`${len}个字节:${buf8.toString('utf8',0,len)}`);
    // 输出: 12 个字节: ½ + ¼ = ¾
    
  • (2) 从Buffer实例读取数据:使用 buf.toString() 方法从Buffer实例读取字符串,也可以使用其他专用方法如 buf.readInt8() 从Buffer实例读取其他类型的数据

    const buf = Buffer.from([-1, 5]);
    console.log(buf.readInt8(0));// 输出结果: -1
    console.log(buf.readInt8(1));// 输出结果: 5
    console.log(buf.readInt8(2));// 抛出异常 ERR_OUT_OF_RANGE(超出范围)
    
  • (3) Buffer实例合并:使用 Buffer.concat() 方法
    语法: Buffer.concat(list[, totalLength])

  • (4) Buffer实例复制:使用 buf.copy() 方法
    语法:buf.copy(target[, targetStart[, sourceStart[, sourceEnd]]])

  • (5) Buffer实例切片:使用 buf.slice() 方法
    语法: buf.slice([start[, end]])

  • 流可以看作是某段时间内从一个点移动到另一个点的数据序列

  • Node.js中的流用于管理和处理数据,使用流完成对大量数据的操作以及逐段处理的操作

  • 流是Node.js中处理流式数据的抽象接口

  • stream模块用于构建实现了流接口的对象 。主要用于开发人员创建新类型的流实例

    const stream = require('stream');
    

流的基本类型:

  • 可写流(Writable)
  • 可读流(Readable)
  • 双工流(Duplex)
  • 转换流(Transform)

流的实现类型:

  • 普通的流:基于字符串和Buffer(或Uint8Array)工作
  • 对象模式的流:使用其他类型的JavaScript值工作

可写流和可读流 都会在内部的缓冲器中存储数据,可缓冲的数据大小取决于传入流构造函数的highWaterMark选项(相当于水位线)。

双工流和转换流 都是可读又可写的,各自维护着两个相互独立的内部缓冲器用于读取和写入。在维护数据流时,读取和写入两端可以各自独立地工作。

可读流

  • 可读流是对提供数据的来源的一种抽象。所有可读流都实现了stream.Readable类定义的接口
  • 可读流有两种模式:流动(Flowing)和暂停(Paused)

  • stream.Readable类定义的主要事件

    • data:当有数据可读时被触发
    • end:没有更多的数据可读时被触发
    • close:当流或其底层资源被关闭时被触发
  • stream.Readable类定义的主要方法

    • readable.read([size]):从内部缓冲区拉取并返回数据
    • readable.pause():使流动模式的流停止触发data事件,并切换出流动模式
    • readable.setEncoding(encoding):为从可读流读取的数据设置字符编码

操作示例:

const fs = require('fs')
//以流的方式读取文件
var readStream=fs.createReadStream('d:/demo.txt');
var str='';//保存数据
readStream.on('data',function(chunk){
    str+=chunk;
})
//读取完成
readStream.on('end',function(chunk){
    console.log(str);
})
//读取失败
readStream.on('error',function(err){
    console.log(err);
})

可写流

  • 可写流是对数据被写入的目的地的一种抽象
  • 所有可写流都实现了 stream.Writable类 定义的接口
  • stream.Writable类定义的主要事件
    • close:当流或其底层资源被关闭时被触发
    • error:写入数据发生错误时被触发
    • finish:调用stream.end()方法且缓冲数据都已传给底层系统之后被触发
  • stream.Writable类定义的主要方法
    • writable.write(chunk[, encoding][,callback]):写入数据到流,并在数据被完全处理之后调用回调函数。

操作示例:

const fs = require('fs')
var str = '这首歌真的很好听呢';
// 创建一个可以写入的流,写入到文件output.txt 中
var writerStream = fs.createWriteStream('d:/output.txt');
// 使用 utf8 编码写入数据
writerStream.write(str,'UTF8');
// 标记文件末尾
writerStream.end();
// 处理流事件
writerStream.on('finish', function() {
    console.log('写入完成!');
});
writerStream.on('error', function(err){
    console.log('写入失败');
});

管道读写操作

  • 管道操作将从一个流中获取的数据传递到另外一个流中
  • 可读流提供的 readable.pipe() 方法在可读流与可写流之间架起桥梁
  • 语法:readable.pipe(destination[, options])
  • 将可读流的所有数据通过管道推送到文件的示例 :
    const readable = getReadableStreamSomehow();//创建一个可读流 
    const writable = fs.createWriteStream('d:/file.txt'); // 创建一个可写流 
    readable.pipe(writable); //管道读写操作,将readable 的所有数据都推送到文件file.txt 
    
  • 在单个可读流上绑定多个可写流,对流进行 链式管道操作(zip) 的示例:
    const fs = require('fs');
    const r = fs.createReadStream('d:/file.txt');
    const z = zlib.createGzip(); 
    const w = fs.createWriteStream('d:file.txt.gz'); 
    r.pipe(z).pipe(w);// 链式管道操作两个可写流
    
  • 默认当来源可读流触发end事件时,目标可写流也会调用 stream.end() 结束写入
  • 禁用默认行为,end选项设为false,目标流就会保持打开状态
    reader.pipe(writer, { end: false });
    reader.on('end', () => {
      writer.end('结束');
    });
    
  • 可读流发生错误,目标可写流不会自动关闭,需要手动关闭所有流以避免内存泄漏
  • readable.unpipe() 方法用于解绑之前使用stream.pipe()方法绑定的可写流

以上是关于Node.js 全局对象Buffer对象流的主要内容,如果未能解决你的问题,请参考以下文章

Node.js系列:Buffer类的使用

Node.js——Buffer

每日灵魂一问-node.js的全局对象有哪些?

Node.js 的 Global全局对象

Node.js的Buffer(缓冲区)和Stream

Node的文件系统及Buffer概述