我需要读取node-js中的一个大型zip文件并处理每个文件(大约100MB的zip文件包含大约40.000个XML文件,每个文件500kb未压缩)。我正在寻找一个具有可接受速度的“流媒体”解决方案,并且不需要将整个数据集保存在内存中(JSZip,node-zip对我有效,但它将所有内容保存在RAM中并且性能不够好)。对c#的快速尝试表明,在2岁的笔记本电脑上使用DotNetZip
可以在大约9秒内完成加载,解包和解析XML。我不认为nodejs会那么快,但是不到一分钟就可以了。将文件解压缩到本地磁盘然后处理它不是一种选择。
我目前正在尝试使用unzip
模块(https://www.npmjs.org/package/unzip),但无法使其正常工作,所以我不知道速度是否合适,但至少它看起来像我可以流式传输每个文件并在回调中处理它。 (问题是我只接收前两个条目,然后它停止调用.on('entry', callback)
回调。我没有收到任何错误,它只是在2个文件后静默停止。我也很高兴知道我是怎么回事可以在一个块中获取完整的XML,而不是在缓冲区之后获取缓冲区。)
function openArchive(){
fs.createReadStream('../../testdata/small2.zip')
.pipe(unzip.Parse())
.on('entry', function (entry) {
var fileName = entry.path;
var type = entry.type; // 'Directory' or 'File'
var size = entry.size;
console.log(fileName);
entry.on('data', function(data){
console.log("received data");
});
});
}
有很多用于处理zip文件的node-js模块,所以这个问题实际上是要找出最适合这种情况的库。
答案 0 :(得分:0)
你必须调用.autodrain()或管道数据到另一个流
entry.on('data', function(data) {
entry.autodrain();
// or entry.pipe(require('fs').createWriteStream(entry.path))
});
答案 1 :(得分:0)
我有相同的任务要做:处理100+ MB的zip存档,每个存档中包含100000+的XML文件。在这种情况下,解压缩磁盘上的文件只会浪费HD空间。我尝试使用adm-zip,但是它将在RAM中加载并扩展整个存档,而我的脚本将在大约1400 MB RAM使用时中断。
使用问题中的代码以及Dilan的回答的精妙提示,有时我只会得到部分XML内容,这当然会破坏我的XML解析器。
经过一些试验,我最终得到了该代码:
// process one .zip archive
function process_archive(filename) {
fs.createReadStream(filename)
.pipe(unzip.Parse())
.on('entry', function (entry) {
// entry.path is file name
// entry.type is 'Directory' or 'File'
// entry.size is size of file
const chunks = [];
entry.on('data', (data) => chunks.push(data));
entry.on('error', (err) => console.log(err));
entry.on('end', () => {
let content = Buffer.concat(chunks).toString('utf8');
process_my_file(entry.path, content);
entry.autodrain();
});
});
return;
}
如果这可以帮助任何人,那么它运行起来非常快并且对我来说效果很好,仅使用最大25 MB的RAM。