Node.js数据流Stream之Readable流和Writable流用法
引言
在Node.js中,数据流(Stream)是一种处理数据的抽象接口,可以将数据读入或写出到内存,文件或网络等多种数据源和目标。Stream接口的主要好处是可以分块处理大量的数据,避免一次性将整个数据读入或写出而导致的内存占用和性能问题。其中Readable流和Writable流是Stream接口中最基础且常用的两种流类型。本文将详细讲解这两种流的用法,帮助读者理解Node.js数据流的核心概念和使用技巧。
Readable流
创建Readable流
创建Readable流的最简单方式是使用fs.createReadStream()方法,该方法可以让我们从文件中读取数据并创建一个可读流对象。下面是一个例子,读取当前目录下的test.txt文件并输出其内容:
const fs = require('fs');
const readStream = fs.createReadStream('./test.txt');
readStream.on('data', (chunk) => console.log(chunk.toString()));
在上面的例子中,我们使用了createReadStream()方法创建了一个可读流对象readStream,每次读取一块数据时会触发'data'事件,我们可以通过监听该事件来获取数据块的内容,并调用toString()转换为字符串后输出到控制台。这里的chunk参数代表读取到的数据块。
暂停和恢复Readable流
默认情况下,Readable流以最大速度不断地推送数据,因此可能会导致内存占用过高或数据丢失的问题。我们可以使用暂停和恢复方法来控制流的速度和状态。
暂停流
我们可以使用pause()方法暂停流的读取操作,这样就可以停止流的任何数据输出操作。当我们需要停止数据推送时,需要调用流的pause()方法,代码如下:
readStream.on('data', (chunk) => {
console.log(chunk.toString());
readStream.pause();
});
在上面的例子中,我们在读取完一个数据块后调用了pause()方法,这将阻止Readble流继续从底层资源读取数据。
恢复流
我们可以使用resume()方法来恢复读取流,从而继续生成数据推送。当我们需要恢复数据输出时,需要调用流的resume()方法,代码如下:
readStream.on('data', (chunk) => {
console.log(chunk.toString());
readStream.pause();
setTimeout(() => {
readStream.resume();
}, 1000);
});
在上面的例子中,我们在读取完一个数据块后不仅调用了pause()方法暂停流的读取操作,还延迟了1秒钟后再次调用了resume()方法,这将允许更多的数据推送进来。
绑定end事件
当读取完所有数据时,Readable流会触发end事件,我们可以在回调函数中执行一些清理操作或者输出流结束的提示信息等。示例如下:
readStream.on('end', () => {
console.log('文件读取完毕!');
});
链式创建流
Readable流支持链式创建流,这样可以让我们将多个流连接起来依次处理数据。例如,在上面读取文件的例子中,我们可以将读取流和输出流连接起来,将读取到的数据写入到另一个文件:
const fs = require('fs');
const readStream = fs.createReadStream('./test.txt');
const writeStream = fs.createWriteStream('./output.txt');
readStream.pipe(writeStream);
在上面的代码中,我们使用了pipe()方法将读取流readStream连接到写入流writeStream,其中数据将从readStream流中读取,经过一系列处理后写入writeStream流中。
Writable流
创建Writable流
Writable流用于将数据写入到指定的数据源,例如文件、HTTP请求体和TCP套接字等。我们可以使用createWriteStream()方法创建Writable流对象,并向其中写入数据。下面是一个例子,将一个字符串写入到文件output.txt中:
const fs = require('fs');
const writeStream = fs.createWriteStream('./output.txt');
writeStream.write('Hello World!');
在上面的例子中,我们使用createWriteStream()方法创建了一个可写流对象writeStream,然后使用write()方法写入了一个字符串'Hello World!'到文件中。
模拟HTTP POST请求
我们可以使用Writable流来模拟HTTP POST请求,向服务器发送表单数据或者JSON数据等。下面是一个例子,使用http模块向网站发送POST请求:
const http = require('http');
const options = {
hostname: 'www.example.com',
path: '/foo',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
};
const request = http.request(options, (res) => {
console.log(`statusCode: ${res.statusCode}`);
});
request.on('error', (error) => {
console.error(error);
});
request.write('data1=value1&data2=value2');
request.end();
在上面的例子中,我们创建了一个http.request对象,并传入服务器地址、端口、请求方法和请求头等信息。然后使用该对象的write()方法向服务器发送表单数据,最后使用end()方法结束请求并向服务器发送数据。
链式创建流
Writable流也支持链式创建流,例如将一个文件读取流和一个网络请求连接起来,将读取到的内容发送到指定的HTTP服务器:
const fs = require('fs');
const http = require('http');
const options = {
hostname: 'www.example.com',
path: '/foo',
method: 'POST',
headers: {
'Content-Type': 'application/octet-stream'
}
};
const readStream = fs.createReadStream('./test.txt');
const request = http.request(options, (res) => {
console.log(`statusCode: ${res.statusCode}`);
});
readStream.pipe(request);
在上面的代码中,我们使用fs.createReadStream()方法将文件读取为一个可读流对象readStream,使用http.request()方法创建一个http请求对象request,并将readStream和request对象通过pipe()方法进行连接。
结论
Readable流和Writable流是Node.js中数据流Stream接口的最基础和最常用的两种流类型。Readable流用于从数据源(如文件、网络、或者内存等)中将数据分块读取到内存中进行处理,而Writable流用于将处理完成的数据分块写入到目标数据源中(如文件、网络、或者内存等)。了解这两种流的基本操作和使用技巧是每个Node.js开发者必备的技能,能够帮助我们更好地处理和管理各种数据源和目标,提高Node.js应用程序的性能和稳定性。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Node.js数据流Stream之Readable流和Writable流用法 - Python技术站