nodejs Stream 流

97 阅读2分钟

用 Stream 创建大文件

我们首先创建一个可写流,向文件里多次写入内容。 最后记得关闭流,得到一个大文件。

复制代码
// 引入文件模块
const fs = require('fs');

const stream = fs.createWriteStream('./../big_file.txt');

for (let i = 0; i < 1000000; i++) {
  stream.write(`这是第${i}行内容\n`);
}

stream.end()
console.log('done')

使用 readFile

我们先使用 fs.readFile 来读取文件内容,看看会发生什么。

复制代码
const fs = require('fs')
const http = require('http')
const server = http.createServer()
server.on('request', (request, response) => {
  fs.readFile('./../big_file.txt', (error, data) => {
    if (error) throw error
    response.end(data)
    console.log('done')
  })
})
server.listen(8889)
console.log(8889)

使用 readFile

当我们访问 http://localhost:8889 的时候,服务器会异步读取这个大文件。

看起来一切正常,没什么毛病。

但是,我们用任务管理器查看 Node.js 的内存,大概占用 130Mb。

服务器接收 1 次请求,占用 130 Mb;那如果接受 10 次请求,就是占用 1G。 对服务器的内存消耗是很大的。

怎么解决这个问题呢?使用 Stream。

使用 Stream

我们来试试用 Stream 改写上面的例子。

创建一个可读流 createReadStream, 再把文件 streamresponse stream 通过管道 pipe 相连。

复制代码
const fs = require('fs')
const http = require('http')
const server = http.createServer()
server.on('request', (request, response) => {
	const stream = fs.createReadStream('./big_file.txt')
	stream.pipe(response)
})
server.listen(8888)

我们再次查看 node.js 内存占用,基本不会高于 30Mb。

因为每次只传递一小段数据,不会占用很大内存。

const stream = fs.createReadStream('./big_file.txt') stream.pipe(response)

stream 就是一个文件流,下面的 stream 就是我们的 http 流 response。 本来这两个流是没有关系的,现在我们想把文件流的数据传递给 http 流。 很简单,用 pipe 连接就行啦。

常用代码

stream1.pipe(stream2)

  • stream1 是发出数据的流,一个可读流。
  • stream2 是写入数据的流,一个可写流。

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

  • Readable - 可读操作。
  • Writable - 可写操作。
  • Duplex - 可读可写操作.
  • Transform - 操作被写入数据,然后读出结果。

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

  • data - 当有数据可读时触发。
  • end - 没有更多的数据可读时触发。
  • error - 在接收和写入过程中发生错误时触发。
  • finish - 所有数据已被写入到底层系统时触发。

本教程会为大家介绍常用的流操作。


从流中读取数据

创建 input.txt 文件,内容如下:

菜鸟教程官网地址:www.runoob.com

创建 main.js 文件, 代码如下:

var fs = require("fs");
var data = '';

// 创建可读流
var readerStream = fs.createReadStream('input.txt');

// 设置编码为 utf8。
readerStream.setEncoding('UTF8');

// 处理流事件 --> data, end, and error
readerStream.on('data', function(chunk) {
   data += chunk;
});

readerStream.on('end',function(){
   console.log(data);
});

readerStream.on('error', function(err){
   console.log(err.stack);
});

console.log("程序执行完毕");