假设我有一个包含100K +甚至500k +文件的目录。我想用fs.readdir
读取目录,但它的异步不是流。有人告诉我,在完成读取整个文件列表之前,异步使用内存。
那么解决方案是什么?我想用流方法readdir。我可以吗?
答案 0 :(得分:7)
在现代计算机中,遍历具有500K文件的目录不算什么。当您在Node.js中异步fs.readdir
时,它所做的只是读取指定目录中的文件名列表。它没有读取文件'内容。我刚刚在dir中测试了700K文件。加载此文件名列表只需21MB内存。
一旦你加载了这个文件名列表,你就可以通过设置一些并发限制来逐个或并行地遍历它们,你可以轻松地全部使用它们。例如:
var async = require('async'),
fs = require('fs'),
path = require('path'),
parentDir = '/home/user';
async.waterfall([
function (cb) {
fs.readdir(parentDir, cb);
},
function (files, cb) {
// `files` is just an array of file names, not full path.
// Consume 10 files in parallel.
async.eachLimit(files, 10, function (filename, done) {
var filePath = path.join(parentDir, filename);
// Do with this files whatever you want.
// Then don't forget to call `done()`.
done();
}, cb);
}
], function (err) {
err && console.trace(err);
console.log('Done');
});
答案 1 :(得分:1)
现在有一种异步迭代的方法!您可以这样做:
const dir = fs.opendirSync('/tmp')
for await (let file of dir) {
console.log(file.name)
}
要将其转换为流:
const _pipeline = util.promisify(pipeline)
await _pipeline([
Readable.from(dir),
... // consume!
])
答案 2 :(得分:-1)
对此仍然没有好的解决方案。节点还不那么成熟。
现代文件系统可以轻松处理目录中的数百万个文件。因此,正如您所建议的,您可以在大规模操作中为其提供理由。
底层C库按需遍历目录列表,一次一次。但是我见过的所有声称要进行迭代的节点实现都使用fs.readdir,它将所有内容尽快读取到内存中。
据我了解,您必须等待将libuv的新版本引入节点。然后让维护者解决这个旧问题。请参见https://github.com/nodejs/node/issues/583
的讨论