我想我已经回答了我的问题。
为了从文件中读取,我使用了
fs.createReadStream(path[, options])
方法返回一个新的 ReadStream 对象 (doc)。
Node.js 中有 4 种类型的流(Readable、Writable、Duples 和 Transform)(doc)。可读流和可写流都将数据存储在内部缓冲区中。可能缓冲的数据量取决于传递给流构造函数的 highWaterMark 选项。
对于普通流(从字符串或缓冲区对象构建的流),highWaterMark 选项指定总字节数。对于在对象模式下运行的流(基于 Javascript 对象的流),highWaterMark 指定对象的总数。
从Implementing a Readable stream 您可以看到 highWaterMark 值默认为 16384 字节(或 16 KB)(对象模式下的流到 16 个对象),并且从fs.createReadStream(path[, options]) 方法你可以透露
与在可读流 (16 kb) 上为 highWaterMark 设置的默认值不同,此方法返回的流具有相同参数的默认值 64 kb。
因此,默认情况下 fs.createReadStream(path[, options] 方法返回的 ReadStream 对象的 highWaterMark 设置为 65536 字节 (64 KB)。
现在我可以检查我的代码了。我存储到文件中的字符串大小为 7372801 字节。当我使用 fs.createReadStream(path[, options] 方法从这个文件中读取时,我得到 113 块:
// To get a ReadStream object
fs.open(path, 'r', (err, fd) => { // fd - file descriptor
if (err) {
if (err.code === 'ENOENT') {
// path points to nowhere - file does not exist
}
throw err
}
var rStream = fs.createReadStream(path, {fd: fd})
})
顺便说一句,在这里我使用文件描述符来读取文件。来自文档:
如果指定了 fd,ReadStream 将忽略路径参数并使用指定的文件描述符。这意味着不会发出“打开”事件。注意 fd 应该是阻塞的;非阻塞 fds 应该传递给 net.Socket。
// To get number of chunks
var counter = 0
rStream.on('data', (chunk) => {
counter++
})
rStream.on('end', () => {
console.log('Total number of chunks: ' + counter)
})
这是因为 7372801 / 65538 (64 KB) = 112 + 余数 => 113
当我人为地将字符串转换为流时(您可以在文档的实现流部分中找到如何执行此操作的信息,在我的示例中,我创建了一个单独的类):
const Readable = require('stream').Readable;
const util = require('util');
function MyReadable(str, options) {
if (!(this instanceof MyReadable))
return new MyReadable(str, options);
Readable.call(this, options);
this.str = str;
}
util.inherits(MyReadable, Readable);
MyReadable.prototype._read = function(size){
var chunk = this.str.slice(0, size)
if(chunk){
this.str = this.str.slice(size)
this.push(chunk)
} else {
this.push(null);
}
}
module.exports = MyReadable;
// Then
var MyReadable = require('./filename')
var stream = new MyReadable(myString, {highWaterMark: 65536} ) // highWaterMark is in bytes
自从我将 highWaterMark 选项重新设置为 64KB 后,上述流也提供了 113 个块。
在 Node.js 中,要获取字符串中的字节数,可以使用Buffer.byteLength(string[, encoding]) 方法。编码默认为“utf8”。
要从可读流中获取缓冲区,您可以使用
rStream._readableState.buffer
来自可写流 ->
wStream._writableState.getBuffer()
所以,现在我可以使用 highWaterMark 选项来管理块。