• Buffer和Stream


    Buffer

    JavaScript 语言自身只有字符串数据类型,没有二进制数据类型。但在处理像TCP流或文件流时,必须使用到二进制数据。

    因此在 Node.js中,定义了一个 Buffer 类,该类用来创建一个专门存放二进制数据的缓存区。

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

    原始数据存储在 Buffer 类的实例中。一个 Buffer 类似于一个整数数组,但它对应于 V8 堆内存之外的一块原始内存。

    1.Buffer对象
    Buffer对象类似于数组,它的元素为16进制的两位数,即0到255的数值。示例代码如下:

    1 var str = "深入浅出node.js";
    2 var buf = new Buffer(str, 'utf-8');
    3 console.log(buf); 
    4 //<Buffer e6 b7 b1 e5 85 a5 e6 b5 85 e5 87 ba 6e 6f 64 65 2e 6a 73>

    上述中的中文字在UTF-8编码下占用3个元素,其余各占用一个元素。

    2.字符串转换Buffer
    字符串转Buffer对项主要是通过构造函数完成的:new Buffer(str,[encoding]);
    通过构造函数转换的Buffer对象,存储的只能是一种编码类型。encoding 参数不传参时,默认按utf-8编码进行转码。

    3.Buffer转字符串
    Buffer对象的toString()可以将Buffer对象转换为字符串:buf.toString([encoding], [start], [end]);
    可以设置encoding(默认为utf-8),start ,end这3个参数实现整体或者局部的转换。

    Stream

    流是一种抽象的数据结构。想象水流,当在水管中流动时,就可以从某个地方(例如自来水厂)源源不断地到达另一个地方(例如洗手池)。

    我们也可以把数据看成是数据流,比如你敲键盘的时候,就可以把每个字符依次连起来,看成字符流。

    这个流是从键盘输入到应用程序,实际上它还对应着一个名字:标准输入流(stdin)。

    Node.js中Stream 有四种流类型:

    • Readable - 可读操作。

    • Writable - 可写操作。

    • Duplex - 可读可写操作.

    • Transform - 操作被写入数据,然后读出结果。

    所有的 Stream 对象都是 EventEmitter 的实例。常用的事件有:

    • data - 当有数据可读时触发。

    • end - 没有更多的数据可读时触发。

    • error - 在接收和写入过程中发生错误时触发。

    • finish - 所有数据已被写入到底层系统时触发。

    读取型:

    对数据流进行一次性读取:

    readstream1.js

     1 'use strict';
     2 //引入fs模块
     3 var fs = require('fs');
     4 
     5 // 创建一个流:
     6 var rs = fs.createReadStream(__dirname+'/sample.txt', 'utf-8');
     7 var data="";
     8 
     9 //data事件表示流的数据已经可以读取,此时一次性进行读取。
    10 rs.on('data', function (chunk) {
    11     console.log('Data') 
    12     console.log(chunk);
    13     data+=chunk;
    14 });
    15 
    16 //end事件表示这个流已经到末尾,无数据可以读取。
    17 rs.on('end', function () {
    18     console.log('End');
    19     console.log(data);
    20 });
    21 
    22 //error事件表示出错了。
    23 rs.on('error', function (err) {
    24     console.log('ERROR: ' + err);
    25 });
    26 console.log('程序执行完毕');

    当对流进行切割,即限制读取长度,此时将会出现乱码,为避免乱码出现,将采用以下方式进行流操作:

    readstream2.js

    'use strict';
    //引入fs模块
    var fs = require('fs');
    
    // 创建一个流,将文件可读流的每次读取的Buffer长度限制为11:
    var rs = fs.createReadStream(__dirname+'/sample.txt',{highWaterMark: 11});
    var chunks = [];
    var size = 0;
    var i=1;
    
    //data事件表示流的数据已经可以读取,此时将进行多次读取,需要将流进行连接。
    rs.on('data', function (chunk) {
          console.log('Data读取第'+i+++'次');
          chunks.push(chunk);
          size += chunk.length;
    });
    
    //end事件表示这个流已经到末尾,无数据可以读取。
    rs.on('end', function () {
           console.log('End');
    //Buffer.concat()方法封装了从小Buffer对象向大Buffer对象的复制过程。
           let buf =Buffer.concat(chunks, size);
           console.log(buf);
           let str = buf.toString('utf-8');
           console.log(str);
    });
    
    //error事件表示出错了。
    rs.on('error', function (err) {
          console.log('ERROR: ' + err);
    });
     
     
    使用文件描述符来读取文件,以下为异步模式下读取文件的语法格式:
    fs.read(fd, buffer, offset, length, position, callback)

    参数使用说明如下:

    • fd - 通过 fs.open() 方法返回的文件描述符。

    • buffer - 数据写入的缓冲区。

    • offset - 缓冲区写入的写入偏移量。

    • length - 要从文件中读取的字节数。

    • position - 文件读取的起始位置,如果 position 的值为 null,则会从当前文件指针的位置读取。

    • callback - 回调函数,有三个参数err, bytesRead, buffer,err 为错误信息, bytesRead 表示读取的字节数,buffer 为缓冲区对象。

    readfile.js

     1 var fs = require('fs');
     2 var buffer = new Buffer(1024);    //设置缓冲区
     3 
     4 console.log('即将打开文件');
     5 fs.open(__dirname+'/sample.txt', 'r+', function (err, fd) {
     6     if (err) {
     7         console.error(err);
     8     }
     9     console.log('文件打开成功');
    10 
    11     //fs.read(fd, buffer, offset, length, position, callback)
    12     fs.read(fd, buffer, 0, buffer.length, 0, function (err, bytes) {
    13 
    14         if (err) {
    15             console.log(err);
    16         }
    17         console.log(bytes + "字节被读取:");
    18 
    19         // 仅输出读取的字节
    20         if (bytes > 0) {
    21             console.log(buffer.slice(0, bytes).toString());
    22         }
    23         
    24         //关闭文件
    25         fs.close(fd, function(err){
    26          if (err){
    27             console.log(err);
    28          } 
    29          console.log("文件关闭成功");
    30       });
    31     })
    32 })

    写入型:

    writestream.js

     1 'use strict';
     2 
     3 //引入fs模块
     4 var fs = require('fs');
     5 
     6 //写入文本数据
     7 var ws1 = fs.createWriteStream(__dirname+'/output1.txt', 'utf-8');
     8 //写数据
     9 ws1.write('使用Stream写入文本数据...
    ');
    10 ws1.write('END.');
    11 // 标记文件末尾
    12 ws1.end();
    13 // 处理流事件 --> data, end, and error
    14 ws1.on('finish',function(){
    15     console.log('写入完成');
    16 });
    17 ws1.on('error', function(err){
    18    console.log(err.stack);
    19 });
    20 
    21 //写入二进制数据
    22 var ws2 = fs.createWriteStream(__dirname+'/output2.txt');
    23 ws2.write(new Buffer('使用Stream写入二进制数据...
    ', 'utf-8'));
    24 ws2.write(new Buffer('END.', 'utf-8'));
    25 ws2.end();
    26 ws2.on('finish',function(){
    27     console.log('写入完成');
    28 });
    29 ws2.on('error', function(err){
    30    console.log(err.stack);
    31 });
    32 
    33 console.log("程序执行完毕");

     注:该模块的更多使用方法:http://www.runoob.com/nodejs/nodejs-fs.html

  • 相关阅读:
    IE678下,select 诡异的样式
    跟着我一步一步的搭建一个基于springcloud的微服务实例
    关于Future踩过的坑
    Apache下的SocketClient的使用
    Jaxb处理泛型,转化成xml字符串
    Linux Centos虚拟机扩容
    docker 搭建zookeeper集群和kafka集群
    sysbench 数据库性能测试工具的使用
    docker 容器技术
    自己手写实现Dubbo
  • 原文地址:https://www.cnblogs.com/jfl-xx/p/7229459.html
Copyright © 2020-2023  润新知