全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

深入nodejs中流(stream)的理解

nodejs的fs模块并没有提供一个copy的方法,但我们可以很容易的实现一个,比如:

var source = fs.readFileSync('/path/to/source', {encoding: 'utf8'});
fs.writeFileSync('/path/to/dest', source);

这种方式是把文件内容全部读入内存,然后再写入文件,对于小型的文本文件,这没有多大问题,比如grunt-file-copy就是这样实现的。但是对于体积较大的二进制文件,比如音频、视频文件,动辄几个GB大小,如果使用这种方法,很容易使内存“爆仓”。理想的方法应该是读一部分,写一部分,不管文件有多大,只要时间允许,总会处理完成,这里就需要用到流的概念。

如上面高大上的图片所示,我们把文件比作装水的桶,而水就是文件里的内容,我们用一根管子(pipe)连接两个桶使得水从一个桶流入另一个桶,这样就慢慢的实现了大文件的复制过程。

Stream在nodejs中是EventEmitter的实现,并且有多种实现形式,例如:

  • http responses request
  • fs read write streams
  • zlib streams
  • tcp sockets
  • child process stdout and stderr

上面的文件复制可以简单实现一下:

var fs = require('fs');
var readStream = fs.createReadStream('/path/to/source');
var writeStream = fs.createWriteStream('/path/to/dest');

readStream.on('data', function(chunk) { // 当有数据流出时,写入数据
  writeStream.write(chunk);
});

readStream.on('end', function() { // 当没有数据时,关闭数据流
  writeStream.end();
});

上面的写法有一些问题,如果写入的速度跟不上读取的速度,有可能导致数据丢失。正常的情况应该是,写完一段,再读取下一段,如果没有写完的话,就让读取流先暂停,等写完再继续,于是代码可以修改为:

var fs = require('fs');
var readStream = fs.createReadStream('/path/to/source');
var writeStream = fs.createWriteStream('/path/to/dest');

readStream.on('data', function(chunk) { // 当有数据流出时,写入数据
  if (writeStream.write(chunk) === false) { // 如果没有写完,暂停读取流
    readStream.pause();
  }
});

writeStream.on('drain', function() { // 写完后,继续读取
  readStream.resume();
});

readStream.on('end', function() { // 当没有数据时,关闭数据流
  writeStream.end();
});

或者使用更直接的pipe

// pipe自动调用了data,end等事件
fs.createReadStream('/path/to/source').pipe(fs.createWriteStream('/path/to/dest'));

下面是一个更加完整的复制文件的过程

var fs = require('fs'),
  path = require('path'),
  out = process.stdout;

var filePath = '/Users/chen/Movies/Game.of.Thrones.S04E07.1080p.HDTV.x264-BATV.mkv';

var readStream = fs.createReadStream(filePath);
var writeStream = fs.createWriteStream('file.mkv');

var stat = fs.statSync(filePath);

var totalSize = stat.size;
var passedLength = 0;
var lastSize = 0;
var startTime = Date.now();

readStream.on('data', function(chunk) {

  passedLength += chunk.length;

  if (writeStream.write(chunk) === false) {
    readStream.pause();
  }
});

readStream.on('end', function() {
  writeStream.end();
});

writeStream.on('drain', function() {
  readStream.resume();
});

setTimeout(function show() {
  var percent = Math.ceil((passedLength / totalSize) * 100);
  var size = Math.ceil(passedLength / 1000000);
  var diff = size - lastSize;
  lastSize = size;
  out.clearLine();
  out.cursorTo(0);
  out.write('已完成' + size + 'MB, ' + percent + '%, 速度:' + diff * 2 + 'MB/s');
  if (passedLength < totalSize) {
    setTimeout(show, 500);
  } else {
    var endTime = Date.now();
    console.log();
    console.log('共用时:' + (endTime - startTime) / 1000 + '秒。');
  }
}, 500);

可以把上面的代码保存为copy.js试验一下

我们添加了一个递归的setTimeout(或者直接使用setInterval)来做一个旁观者,每500ms观察一次完成进度,并把已完成的大小、百分比和复制速度一并写到控制台上,当复制完成时,计算总的耗费时间,效果如图:

我们复制了一集1080p的权利的游戏第四季第7集,大概3.78G大小,由于使用了SSD,可以看到速度还是非常不错的,哈哈哈~ 复制完成后,显示总花费时间

结合nodejs的readlineprocess.argv等模块,我们可以添加覆盖提示、强制覆盖、动态指定文件路径等完整的复制方法,有兴趣的可以实现一下,实现完成,可以

ln -s /path/to/copy.js /usr/local/bin/mycopy

这样就可以使用自己写的mycopy命令替代系统的cp命令

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


# node  # stream  # node.js  # stream流  # nodejs  # 快速了解Node中的Stream流是什么  # node.js使用stream模块实现自定义流示例  # Node.js中你不可不精的Stream(流)  # 详解nodeJs文件系统(fs)与流(stream)  # Node.js中流(stream)的使用方法示例  # Nodejs Stream 数据流使用手册  # Node.js中的流(Stream)介绍  # 说说node中的可读流和可写流的区别  # 浅谈手写node可读流之流动模式  # node.js中stream流中可读流和可写流的实现与使用方法实例分析  # 写完  # 很容易  # 我们可以  # 如果没有  # 递归  # 应该是  # 是一个  # 几个  # 有可能  # 有多  # 有兴趣  # 可以看到  # 然后再  # 总会  # 可以实现  # 写到  # 如图  # 有多大  # 所示  # 来做 


相关文章: 临沂网站制作公司有哪些,临沂第四中学官网?  桂林网站制作公司有哪些,桂林马拉松怎么报名?  我的世界制作壁纸网站下载,手机怎么换我的世界壁纸?  成都网站制作公司哪家好,四川省职工服务网是做什么用?  东莞专业制作网站的公司,东莞大学生网的网址是什么?  厦门模型网站设计制作公司,厦门航空飞机模型掉色怎么办?  网站图片在线制作软件,怎么在图片上做链接?  网站设计制作企业有哪些,抖音官网主页怎么设置?  详解ASP.NET 生成二维码实例(采用ThoughtWorks.QRCode和QrCode.Net两种方式)  北京网站制作公司哪家好一点,北京租房网站有哪些?  如何制作一个表白网站视频,关于勇敢表白的小标题?  如何用搬瓦工VPS快速搭建个人网站?  微信小程序 五星评分(包括半颗星评分)实例代码  如何零基础在云服务器搭建WordPress站点?  国美网站制作流程,国美电器蒸汽鍋怎么用官方网站?  c++ stringstream用法详解_c++字符串与数字转换利器  建站之星免费模板:自助建站系统与智能响应式一键生成  建站之星如何快速生成多端适配网站?  建站主机CVM配置优化、SEO策略与性能提升指南  c++23 std::expected怎么用 c++优雅处理函数错误返回【详解】  如何选择PHP开源工具快速搭建网站?  高端网站建设与定制开发一站式解决方案 中企动力  如何用花生壳三步快速搭建专属网站?  武清网站制作公司,天津武清个人营业执照注销查询系统网站?  东莞专业网站制作公司有哪些,东莞招聘网站哪个好?  手机网站制作平台,手机靓号代理商怎么制作属于自己的手机靓号网站?  如何用手机制作网站和网页,手机移动端的网站能制作成中英双语的吗?  广州美橙建站如何快速搭建多端合一网站?  标准网站视频模板制作软件,现在有哪个网站的视频编辑素材最齐全的,背景音乐、音效等?  如何选择靠谱的建站公司加盟品牌?  如何快速搭建高效WAP手机网站?  网站制作服务平台,有什么网站可以发布本地服务信息?  相册网站制作软件,图片上的网址怎么复制?  如何通过主机屋免费建站教程十分钟搭建网站?  深圳网站制作案例,网页的相关名词有哪些?  如何自定义建站之星模板颜色并下载新样式?  微信网站制作公司有哪些,民生银行办理公司开户怎么在微信网页上查询进度?  专业网站制作企业网站,如何制作一个企业网站,建设网站的基本步骤有哪些?  SAX解析器是什么,它与DOM在处理大型XML文件时有何不同?  ,怎么在广州志愿者网站注册?  建站之星价格显示格式升级,你的预算足够吗?  北京企业网站设计制作公司,北京铁路集团官方网站?  图片制作网站免费软件,有没有免费的网站或软件可以将图片批量转为A4大小的pdf?  如何在阿里云虚拟机上搭建网站?步骤解析与避坑指南  如何通过商城免费建站系统源码自定义网站主题?  简历在线制作网站免费版,如何创建个人简历?  ,制作一个手机app网站要多少钱?  网站制作公司排行榜,四大门户网站排名?  如何在Golang中实现微服务服务拆分_Golang微服务拆分与接口管理方法  简易网站制作视频教程,使用记事本编写一个简单的网页html文件? 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。