[关闭]
@Wangww0925 2019-08-07T08:02:54.000000Z 字数 3355 阅读 207

stream 流

NodeJs


流操作(stream) 一般代表文件读写操作

什么是流

把一个文件比喻成一个水桶,文件里面的内容比作为水,我们用一根管子(pipe)连接两个桶使得水从一个桶流入另一个桶,这样就慢慢的实现了大文件的复制过程(也就是流的过程)。

为什么要有流操作

如果读取或者写入一个比较大的文件如(音频或者视频一般为几个G左右),如果使用writeFile或者readFile来操作,非常容易使电脑内存"爆仓",因为电脑内存一般也就4G,8G左右

理想的方法应该是分多次对数据进行读写操作,不管文件有多大,只要时间允许,总会处理完成。这时后就需要有流操作了

Stream 有四种流类型:

所有可以读取数据的流都继承自stream.Readable
所有可以写入的流都继承自stream.Writable



fs.createReadStream(file) 可读流

从文件读取数据时,可以打开一个文件流,然后从文件流中不断地读取数据

方法

  1. pause() - 可读流读取暂停
  2. resume() - 可读流读取继续

事件

  1. data - 监听可读流读取数据事件
  2. chunk - 数据存储在chunk
  3. error - 监听可读流读取失败事件
  4. end - 监听可读流读取结束事件

例子

  1. var fs = require("fs");
  2. var readStream = fs.createReadStream("./guilai.mp4"); //创建一个可读流
  3. readStream.on("data",function(chunk){
  4. console.log(chunk);
  5. })
  6. readStream.on("error",function(err){
  7. console.log(err);
  8. })
  9. readStream.on("end",function(){
  10. console.log("读取完毕")
  11. })

fs.createWriteStream(file) 可写流

向文件写入数据时,只需要把数据不断地往文件流中写进去就可以了

PS: 文件不存在则会先创建文件

方法

  1. write() - 向文件中写入内容 【要写入多个内容,只需要不断调用这个函数就可以了】
  2. - write() 返回布尔值,true - 写入流完成,false - 未完成
  3. end() - 标记文件末尾

事件

  1. error - 监听可写流写入失败事件
  2. finish - 监听可写流写入结束事件
  3. drain - 监听可写流完成后触发事件

例子

  1. var fs = require("fs");
  2. var writeStream = fs.createWriteStream("03.txt"); // 创建一个可写流
  3. writeStream.write("哈哈哈哈");
  4. writeStream.write("html css javascript");
  5. writeStream.end(); // 标记文件末尾
  6. writeStream.on('error', function(err){
  7. console.log(err.stack);
  8. });
  9. writeStream.on('finish', function() {
  10. console.log("写入完成");
  11. });

以下所用到的 guilai.mp4 ,由于视频太大无法上传,不过可以用其他音视频代替 guilai.mp4 进行测试


将读到的内容写到新的文件(一)【不推荐】【可写流 结合 可读流】

弊端

如果写入的速度跟不上读取的速度,有可能导致数据丢失

写入到完成耗时长

数据丢失如何解决?

应该写完一段,再读取下一段,如果没有写完的话,就让读取流先暂停,等写完再继续,具体看 【可读流过程的 暂停 readStream.pause() 和 重启 readStream.resume()】

test.txt

  1. hello

node 执行文件

  1. var fs = require("fs");
  2. var readStream = fs.createReadStream("./guilai.mp4"); // 创建可读流
  3. var writeStream = fs.createWriteStream("./www.mp4"); // 创建可写流
  4. readStream.on("data",function(chunk){
  5. writeStream.write(chunk); // 将数据写入www.txt文件中
  6. })
  7. readStream.on("end",function(){
  8. writeStream.end();
  9. })

将读到的内容写到新的文件(二) 【不推荐】【可读流过程的 暂停 readStream.pause() 和 重启 readStream.resume() ,解决数据丢失问题】

writeStream.write(chunk) 返回布尔值,true - 写入流完成,false - 未完成

弊端:写入到完成耗时长

例子

  1. var fs = require("fs");
  2. var readStream = fs.createReadStream("./guilai.mp4"); // 创建可读流
  3. var writeStream = fs.createWriteStream("./www.mp4"); // 创建可写流
  4. readStream.on("data",function(chunk){
  5. if(writeStream.write(chunk) === false){
  6. console.log("暂停");
  7. readStream.pause();
  8. }
  9. })
  10. // drain - 监听可写流完成后触发事件
  11. writeStream.on("drain", function(){
  12. console.log("继续");
  13. readStream.resume();
  14. })
  15. readStream.on("end", function(){
  16. writeStream.end();
  17. })

将读到的内容写到新的文件(三) 【推荐】【pipe中间管道】

pipe中间管道:将可读流和可写流串联起来,一个Readable流和一个Writable流串起来后,所有的数据自动从Readable流进入Writable流,这种操作叫pipe,这样源文件的所有数据就自动写入到目标文件里了

pipe会自动调用data,end等事件

优点: 速度快,代码简洁

例子

  1. var fs = require("fs");
  2. var readStream = fs.createReadStream("./guilai.mp4"); // 创建可读流
  3. var writeStream = fs.createWriteStream("./www.mp4"); // 创建可写流
  4. readStream.pipe(writeStream); // 通过pipe中间管道写入流

将读到的内容写到新的文件并压缩(四) 【推荐】【pipe中间管道 结合 zlib可压缩模块】

例子

  1. var fs = require("fs");
  2. var zlib = require("zlib"); // 引入可压缩模块
  3. var readStream = fs.createReadStream("./guilai.mp4"); // 创建可读流
  4. var writeStream = fs.createWriteStream("./www.mp4.zip"); // 创建可写流
  5. var gzip = zlib.createGzip(); //创建压缩流
  6. readStream.pipe(gzip).pipe(writeStream); // 通过中间管道进行压缩然后写入到可写流中

作者 wendy
2019 年 1月 21日

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注