用 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, 再把文件 stream 和 response 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("程序执行完毕");