1. 先说说各自的用法:

How do I read files in node.js?

fs = require('fs');
fs.readFile(file, [encoding], [callback]);// file = (string) filepath of the file to read

encoding is an optional parameter that specifies the type of encoding to read the file. Possible encodings are 'ascii', 'utf8', and 'base64'. If no encoding is provided, the default is utf8.

callback is a function to call when the file has been read and the contents are ready - it is passed two arguments, error and data. If there is no error, error will be null and data will contain the file contents; otherwise err contains the error message.

So if we wanted to read /etc/hosts and print it to stdout (just like UNIX cat):

fs = require('fs')
fs.readFile('/etc/hosts', 'utf8', function (err,data) {if (err) {return console.log(err);}console.log(data);
});

The contents of /etc/hosts should now be visible to you, provided you have permission to read the file in the first place.

Let's now take a look at an example of what happens when you try to read an invalid file - the easiest example is one that doesn't exist.

fs = require('fs');
fs.readFile('/doesnt/exist', 'utf8', function (err,data) {if (err) {return console.log(err);}console.log(data);
});

This is the output:

{ stack: [Getter/Setter],arguments: undefined,type: undefined,message: 'ENOENT, No such file or directory \'/doesnt/exist\'',errno: 2,code: 'ENOENT',path: '/doesnt/exist' }

How to use fs.createReadStream?

var http = require('http');
var fs = require('fs');http.createServer(function(req, res) {// The filename is simple the local directory and tacks on the requested urlvar filename = __dirname+req.url;// This line opens the file as a readable streamvar readStream = fs.createReadStream(filename);// This will wait until we know the readable stream is actually valid before pipingreadStream.on('open', function () {// This just pipes the read stream to the response object (which goes to the client)readStream.pipe(res);});// This catches any errors that happen while creating the readable stream (usually invalid names)readStream.on('error', function(err) {res.end(err);});
}).listen(8080);

2. 区别:

createReadStream是给你一个ReadableStream,你可以听它的'data',一点一点儿处理文件,用过的部分会被GC(垃圾回收),所以占内存少。 readFile是把整个文件全部读到内存里。

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

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

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

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观察一次完成进度,并把已完成的大小、百分比和复制速度一并写到控制台上,当复制完成时,计算总的耗费时间。

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

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

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

更多fs说明,可以查看API: http://nodeapi.ucdok.com/#/api/fs.html

原文转自:Node.js: fs.readFile/writeFile 和 fs.createReadStream/writeStream 区别

Node.js: fs.readFile/writeFile 和 fs.createReadStream/writeStream 区别相关推荐

  1. node.js浅入深出---fs模块的stat判断是否为文件夹

    判断文件夹下的bbb是否为文件夹,若是的返回true var http = require("http"); var fs = require("fs"); v ...

  2. javascript / node.js / npm install 时 --save 和 --save-dev 的区别

    一.dependencies 和 devDependencies 在使用 node 开发时, 我们在工程中用到的包必须是 package.json 中列出.而 dependencies 和 devDe ...

  3. 33.Node.js 文件系统fs

    转自:http://www.runoob.com/nodejs/nodejs-module-system.html Node.js 提供一组类似 UNIX(POSIX)标准的文件操作API. Node ...

  4. node.js使用手册_权威的Node.js手册

    node.js使用手册 Note: you can get a PDF, ePub, or Mobi version of this handbook for easier reference, or ...

  5. 【前端】-【node.js基础】-学习笔记

    [前端]-[node.js]-学习笔记 1 node.js介绍 1.1 node.js优点 1.2 node.js 不足之处 1.3 nodejs与java的区别 2. node中函数 3. 浏览器和 ...

  6. JavaScript教程9 - Node.js

    Node.js 安装Node.js https://nodejs.org/ npm npm其实是Node.js的包管理工具(package manager). 命令行模式 执行node hello.j ...

  7. node.js 文件重命名||文件复制||删除||追加 增删改查

    文件重命名 //文件处理 const fs = require("fs") //文件路径 const pathToFile = path.join(__dirname, " ...

  8. Node.js 入门详解(一)

    目录 前言 1. 初识 Node.js 1.1 回顾与思考 1.2 Node.js 简介 1.2.1 什么是Node.js 1.2.2 Node.js 中的 JavaScript 运行环境 1.2.3 ...

  9. 【Node.js】node入门全攻略

    文章目录 一.初识 Node.js (一)JS 解析引擎 (二)JS 运行环境 (三)Node.js 1.作用 2.命令 二.fs 文件系统模块 (一)fs 模块 (二)方法 1.fs.readFil ...

最新文章

  1. php将json分页,php处理分页数据并返回json
  2. php调用matlab
  3. cisco routemap 能在出接口调用吗_潍坊驰燃一号燃料能不能合法在家经营,手续好办吗?...
  4. Leetcode 978. 最长湍流子数组
  5. .ai域名注册已经极具投资价值进入火爆期
  6. Vue系列vue-router的参数传递的两种方式(五)
  7. 红魔游戏手机6 Pro氘锋透明版明日开启预售:售价5599元
  8. Biopython SeqIO 读取序列文件,读取信息,写入序列
  9. java测试接口_Java测试普通Java接口记录-TestHrmInterface
  10. 单摆的动力学建模以及matlab仿真(牛顿法和拉格朗日方程法)
  11. 洛谷Java入门级代码之分汽水
  12. python 输入框查询_前端实现输入框input输入时,调用后台查询。
  13. 三诺+n20g+微型计算机,岁月留声 三诺15周年经典回顾
  14. 钢铁侠或漫威中有哪些黑科技?
  15. WIFI知识 - MCS简介
  16. 什么因素让唐僧是一个领导,而孙悟空只是一个打工者呢?
  17. 2021年全球与中国机车(机车车辆)行业市场规模及发展前景分析
  18. jee Java什么意思_JEE、J2EE与Jakarta等概念解释
  19. shiro权限管理的框架、加密、授权
  20. 基于springboot校园二手市场平台

热门文章

  1. 信息学奥赛一本通(1016:整型数据类型存储空间大小)
  2. 整数大小比较(信息学奥赛一本通-T1043)
  3. 信息学奥赛C++语言: 蛇形方阵1
  4. 信息学奥赛一本通C++语言——1083:计算星期几
  5. 计算机应用能力power,全国专业技术人员计算机应用能力考试专用教材——PowerPoint 2003中文演示文稿5日通题库版(双色)(附光盘) - 中国考研网...
  6. linux上 arm开发环境搭建,详解 LINUX下QT For ARM开发环境搭建过程
  7. python有什么用途视频_使用Python管理多平台视频流的最佳方法是什么?
  8. shell正则表达式去除注释行
  9. linux 字符设备驱动cdev
  10. vue项目打包:npm run build 进程卡死