• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
火磷
Memory will fade,but not notes.
博客园    首页    新随笔    联系   管理    订阅  订阅
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写入文本数据...\n');
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写入二进制数据...\n', '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

posted on 2017-07-24 16:06  火磷  阅读(848)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3