一. 可读流: stream.Readable

在Node.js中,各种实现了stream.Readable接口的对象可以将对象数据读取为流数据,所有这些对象都集成了EventEmitter类的实例对象,在读取数据的过程中,将可能触发各种事件。

在Node.js中,可以使用flowing模式与非flowing模式来读取数据。当使用flowing模式时,将使用操作系统内部I/O机制来读取数据,这将允许你以最快的速度来读取数据。当使用非flowing模式时,就必须显式调用对象的read方法来读取数据。

Node.js中的各种用于读取数据的对象如下:

对象 说明
fs.ReadStream 用于读取文件
http.IncomingMessage 代表客户端请求或服务器响应
net.Socket 代表一个socket端口对象
child.stdout 用于创建子进程的标准输出流。如果子进程与父进程共享输入输出流,则子进程的标准输出流被废弃
child.stderror 用于创建子进程的错误输出流。如果子进程与父进程共享输入输出流,则子进程的标准输出流被废弃
process.stdin 用于创建进程的标准输入流
Gzip
Deflate
DeflateRaw
用于实现数据压缩

可读流对象将有可能触发的事件如下:

事件名 说明
readable 当可以从流中读出数据时触发。
data 当读取到来自文件、客户端、服务器端等对象的新数据时触发data事件。参数值为存放了已读取到的数据的缓存区对象或一个字符串(当对流数据指定编码格式时)。如果指定了data事件的回调函数,将使用flowing模式来读取流数据,这允许你以最快速度读出流中的数据
end 当读取完所有数据时触发,该事件的触发以为这data事件将不再内触发
error 当读取数据过程中产生错误时触发
close 当用于读取流数据的对象被关闭时触发。并非所有用于读取流数据的对象都会触发该事件

可读流对象所拥有的方法如下:

方法名 说明
read 用于读取数据
setEncoding 用于指定用什么编码方式读取数据
pause 用于通知对象停止触发data事件
resume 用于通知对象停止触发data事件
pipe 用于设置一个数据通道,然后取出所有流数据并将其输出到通道另一端所指向的目标对象中
unpipe 用于取消在pipe方法中设置的通道
unshift 当对流数据绑定了一个解析器时,可以使用unshift方法来取消该解析器的绑定,使流数据可以通过其他方式解析

二. 可写流: stream.Writeable

在Node.js中,各种实现了stream.Writeable接口的对象来将数据流写入到对象中,所有这些对象都是继承了EventEmitter类的实例对象。

各种用于写入数据的对象如下:

对象 说明
fs.WriteStream 用于写入文件
http.ClientRequest 用于写入HTTP客户端请求数据
http.ServerResponse 用于写入HTTP服务器端响应数据
net.Socket 用于读写TCP流或UNIX流,可被用户创建并作为一个客户端来使用,也可被Node.js脚本程序创建并通过服务器的connection事件来传递给用户
child.stdin 用于创建子进程的标准输入流。使用该对象的close方法将终止子进程。如果子进程与父进程共享输入输出流,则子进程的标准输出流被废弃
child.stdout 用于创建子进程的错误输出流
child.stderror 用于创建子进程的错误输出流
Gzip
Deflate
DeflateRaw
用于实现数据压缩

可写流对象将有可能触发的事件有:

事件 说明
drain 当用于写入数据的write方法返回false之后触发,表示操作系统缓存区中的数据已全部输出到目标对象中,可以继续向操作系统缓存区中写入数据
finish 当end方法被调用且数据被全部写入操作系统缓存区时触发
pipe 当用于读取数据的对象的pipe方法被调用时触发
unpipe 当用于读取数据的对象的unpipe方法被调用时触发
error 当写入数据的过程中产生错误时触发

可写流对象所拥有的方法有:

方法 说明
write 用于写入数据
end 当没有数据再被写入流中时调用该方法。这将迫使操作系统缓存区中的剩余数据被立即写入目标对象中。当该方法被调用后,将不能继续在目标对象中写入数据

三. 使用ReadStream对象读取文件

在fs模块中,可以使用createReadStream()方法创建一个将文件内容读取为流数据的ReadStream对象,该方法的使用方式如下:

 fs.createReadStream(path [, options])

参数:

  • path: 需要被读取的文件的完整路径及文件名;
  • options: 数据类型为对象,可选,其属性值有:
    • flags: 用于指定对该文件采取什么操作,默认值为”r”;
    • encoding: 用于指定使用什么编码格式来读取该文件。可指定属性值为”utf8″、”ascii”、”base64″。默认值为null;
    • autoClose:用于指定是否关闭在读取文件时操作系统内部使用的文件描述符。如果属性值设置为false,则文件不会自动关闭,即使在读取文件过程中产生了错误,开发者也必须通过使用close方法或closeSync方法来手动关闭文件。如果属性值设定为true,则文件读取完毕或读取文件过程中产生错误时,文件将自动关闭。默认值为true;
    • start: 指定文件开始读取位置(单位为字节数);
    • end: 指定文件结束读取位置(单位为字节数)。

实例一:使用ReadStream方法读取文件

var fs = require('fs');

var file = fs.createReadStream("1.js");
file.on("open", function(fd) {
    console.log("开始读取文件:");
});
file.on("data", function(data) {
    console.log("读取到数据:");
     console.log(data);
});
file.on("end", function() {
     console.log("文件已全部读取完毕。");
});
file.on("close", function() {
    console.log("文件被关闭。");
});
file.on("error", function() {
    console.log("读取文件失败。");
});

console打印值如下:

开始读取文件:
读取到数据:
<Buffer 63 6f 6e 73 74 20 6f 73 20 3d 20 72 65 71 75 69 72 65 28 27 6f 73 27 29 3b 0d 0a 0d 0a 76 61 72 20 74 79 70 65 20 3d 20 6f 73 2e 74 79 70 65 28 29 3b>
文件已全部读取完毕。
文件被关闭。

实例二:使用ReadStream方法延时读取文件

打开文件后暂停文件的读取,隔3秒钟后开始读取文件并在控制台中输出文件内容:

var fs = require('fs');

var file = fs.createReadStream("1.js");
file.pause();
file.on("data", function(data) {
    console.log("读取到数据:");
     console.log(data);
});
setTimeout(function() {
    file.resume();
}, 3000);

四. 使用ReadStream对象读取文件

在fs模块中,可以使用createWriteStream()方法创建一个将文件内容读取为流数据的ReadStream对象,该方法的使用方式如下:

 fs.createWriteStream(path [, options])

参数与 fs.createWriteStream()方法的类似。

write()方法:

WriteStream对象具有一个write()方法,用于将数据流写入目标对象,该方法的使用方式如下:

writable.write(trunk, [encoding], [callback])

其中,trunk为一个Buffer对象或一个字符串,用于指定写入的数据。 当trunk为字符串时,可以指定encoding参数值来指定将数据以何种编码方式写入文件。

end()方法

WriteStream对象还具有一个end()方法,用于将数据流写入目标对象,该方法的使用方式如下:

writable.end([trunk], [encoding], [callback])

其中trunk表示在文件关闭之前需要在文件中追加写入的数据。

bytesWritten属性:

另外,WriteStream对象还具有一个bytesWritten属性,属性值为当前已在文件中写入数据的字节数。

实例:文件拷贝

var fs = require('fs');

var file = fs.createReadStream("1.js");
var outputFile = fs.createWriteStream("output.js");
file.on("data", function(data) {
    outputFile.write(data);
});
outputFile.on("open", function(fd) {
    console.log("需要被写入的文件已被打开。");
});
file.on("end", function() {
    outputFile.end("The end.", function() {
        console.log("文件全部写入完毕。");
        console.log("共写入%d字节数据。", outputFile.bytesWritten);
    });
});

console输出值如下:

需要被写入的文件已被打开。
文件全部写入完毕。
共写入206字节数据。

此时,output.js已完整拷贝了1.js中的全部内容。

本文作者:子匠_Zijor,转载请注明出处:http://www.dengzhr.com/node-js/847