我有一个非常大的base64编码字符串,需要读入一个字节(Uint8)数组,然后将该字节数组拆分为指定大小的块,它们分别对这些块进行编码。使用下面的函数可以工作但是调用.slice或.toString会增加每次调用时堆上的内存,因为(我相信)它正在复制缓冲区。在特别大的base64Encoded字符串上,应用程序将在堆上空间不足。可以做些什么来将其拆分为指定的大小,base64对它们进行编码而不会耗尽内存?
const process = function (reallyLargeBase64EncodedString, splitSize){
var theBuffer = Buffer.from(reallyLargeBase64EncodedString, 'base64');
//var tempBuffer = new Buffer(splitSize);
for (var start = 0; start < theBuffer.length; start += splitSize) {
//for(var z = 0; z < splitSize; z++){
//tempBuffer.writeUInt8( theBuffer[start+z],z);
//}
//var base64EncodedVal = tempBuffer.toString('base64');
//var base64EncodedVal = theBuffer.buffer.toString('base64', start, start+splitSize);
var base64EncodedVal = theBuffer.slice(start,start+splitSize).toString('base64');
//do stuff with the base64 encoded value
}
};
答案 0 :(得分:5)
我建议使用node的流媒体接口来处理那些大的东西。如果您的base64编码字符串来自文件或网络请求,您可以直接从输入管道传输到base64解码流,如base64-stream。
为了对数据进行分块并重新编码每个块,您必须编写自己的变换流(输入和输出之间的流)。这看起来像
// NOTE: the following code has been tested in node 6.
// since it relies on the new Buffer api, it must be run in 5.10+
var Transform = require('stream').Transform;
class ChunkEncode extends Transform {
constructor(options){
super(options);
this.splitSize = options.splitSize;
this.buffer = Buffer.alloc(0);
}
_transform(chunk, encoding, cb){
// chunk is a Buffer;
this.buffer = Buffer.concat([this.buffer, chunk]);
while (this.buffer.length > this.splitSize){
let chunk = this.buffer.slice(0, this.splitSize);
// Encode and write back to the stream.
this.push(chunk.toString('base64'))
// throw in a newline for visibility.
this.push('\n');
// chop off `splitSize` from the start of our buffer.
this.buffer = this.buffer.slice(this.splitSize);
}
}
}
然后你应该可以做类似
的事情 var fs = require('fs');
var base64 = require('base64-stream');
fs.createReadStream('./long-base64-string')
.pipe(base64.decode())
.pipe(new ChunkEncode({splitSize : 128}))
.pipe(process.stdout)
这将记录到标准输出,但您可以轻松地写入文件或网络流。如果您需要进一步操作数据,您可以创建一个写入流,这样您就可以对每个数据块执行某些操作。