我在一些书中读到,使用流式传输比在 node.js 中一次读取整个文件更好,我理解这个想法..但我不知道是不是使用文件阅读流,我从Java和C ++习惯这个,当我想读取一个文件时,我使用流..那么这里的区别是什么?
还有fs.createReadStream(<somefile>);
和fs.readFile(<somefile>);
之间的区别
两者都是异步的,对吧!!
答案 0 :(得分:10)
首先是fileread是完全缓冲的方法。流是部分缓冲的方法。
现在是什么意思?
完全缓冲的函数调用,如readFileSync()和readFile()公开 数据作为一个大blob。也就是说,执行读取,然后以同步或异步方式返回完整的数据集。 使用这些完全缓冲的方法,我们必须等到读取所有数据,并且内部Node需要分配足够的内存来存储内存中的所有数据。这可能会有问题 - 想象一下从磁盘读取1 GB文件的应用程序。只有完全缓冲的访问,我们需要使用1 GB的内存来存储文件的整个内容以供读取 - 因为readFile和readFileSync都返回一个包含所有数据的字符串。
部分缓冲的访问方法不同。它们不将数据输入视为离散事件,而是将一系列事件视为正在读取或写入数据时发生的事件。它们允许我们在从磁盘/网络/其他I / O读取数据时访问数据。部分缓冲的访问方法是不同的。它们不将数据输入视为离散事件,而是将一系列事件视为正在读取或写入数据时发生的事件。它们允许我们在从磁盘/网络/其他I / O读取数据时访问数据。
Streams返回较小的数据部分(使用Buffer),并在新数据可供处理时触发回调。
Streams是EventEmitters。例如,如果我们的1 GB文件需要以某种方式处理一次,我们可以使用流并在读取数据后立即对其进行处理。这很有用,因为我们不需要在某个缓冲区中保存内存中的所有数据:在处理之后,我们不再需要将数据保存在内存中以用于此类应用程序。
节点流接口由两部分组成:可读流和可写流。有些流是可读写的。
答案 1 :(得分:7)
那么这里的区别是什么?另外
fs.createReadStream(<somefile>);
和fs.readFile(<somefile>);
之间的区别是异步,对吧!!
除了fs.createReadStream()
直接返回stream
个对象,fs.readFile()
期望第二个参数中有回调函数这一事实外,还有另一个巨大的差异。
是的,它们都是异步的,但这并没有改变fs.readFile()
在整个文件缓冲到内存之前不会提供任何数据的事实。当通过服务器响应中继数据时,这样的内存效率更低,速度更慢。使用fs.createReadStream()
,您可以pipe()
将stream
对象直接发送到服务器的response
对象,这意味着即使文件为500MB,您的客户端也可以立即开始接收数据。
不仅如此,您还可以通过一次处理一个块而不是一次性处理文件来提高内存效率。这意味着你的内存只需要一次缓冲file
内容几千字节而不是一次缓冲。
这里有两个片段,展示了我在说什么:
const fs = require('fs');
const http = require('http');
// using readFile()
http.createServer(function (req, res) {
// let's pretend this is a huge 500MB zip file
fs.readFile('some/file/path.zip', function (err, data) {
// entire file must be buffered in memory to data, which could be very slow
// entire chunk is sent at once, no streaming here
res.write(data);
res.end();
});
});
// using createReadStream()
http.createServer(function (req, res) {
// processes the large file in chunks
// sending them to client as soon as they're ready
fs.createReadStream('some/file/path.zip').pipe(res);
// this is more memory-efficient and responsive
});