gpt4 book ai didi

javascript - 在 Nodejs 中解析大型 JSON 文件

转载 作者:太空宇宙 更新时间:2023-11-03 22:26:46 24 4
gpt4 key购买 nike

我有一个以 JSON 形式存储许多 JavaScript 对象的文件,我需要读取该文件,创建每个对象,并对它们执行一些操作(在我的例子中将它们插入到数据库中)。 JavaScript 对象可以用以下格式表示:

格式A:

[{name: 'thing1'},
....
{name: 'thing999999999'}]

格式B:

{name: 'thing1'}         // <== My choice.
...
{name: 'thing999999999'}

请注意,... 表示许多 JSON 对象。我知道我可以将整个文件读入内存,然后使用 JSON.parse() 像这样:

fs.readFile(filePath, 'utf-8', function (err, fileContents) {
if (err) throw err;
console.log(JSON.parse(fileContents));
});

但是,文件可能非常大,我更愿意使用流来完成此操作。我在流中看到的问题是文件内容可以随时分解为数据 block ,那么如何在此类对象上使用 JSON.parse() 呢?

理想情况下,每个对象都将作为单独的数据 block 读取,但我不确定如何做到这一点

var importStream = fs.createReadStream(filePath, {flags: 'r', encoding: 'utf-8'});
importStream.on('data', function(chunk) {

var pleaseBeAJSObject = JSON.parse(chunk);
// insert pleaseBeAJSObject in a database
});
importStream.on('end', function(item) {
console.log("Woot, imported objects into the database!");
});*/

注意,我希望防止将整个文件读入内存。时间效率对我来说并不重要。是的,我可以尝试一次读取多个对象并一次插入它们,但这是一个性能调整 - 我需要一种保证不会导致内存过载的方法,无论文件中包含多少个对象。

我可以选择使用 FormatAFormatB 或其他内容,请在您的答案中注明。谢谢!

最佳答案

要逐行处理文件,您只需将文件的读取与作用于该输入的代码解耦即可。您可以通过缓冲输入直到遇到换行符来实现此目的。假设我们每行有一个 JSON 对象(基本上是格式 B):

var stream = fs.createReadStream(filePath, {flags: 'r', encoding: 'utf-8'});
var buf = '';

stream.on('data', function(d) {
buf += d.toString(); // when data is read, stash it in a string buffer
pump(); // then process the buffer
});

function pump() {
var pos;

while ((pos = buf.indexOf('\n')) >= 0) { // keep going while there's a newline somewhere in the buffer
if (pos == 0) { // if there's more than one newline in a row, the buffer will now start with a newline
buf = buf.slice(1); // discard it
continue; // so that the next iteration will start with data
}
processLine(buf.slice(0,pos)); // hand off the line
buf = buf.slice(pos+1); // and slice the processed data off the buffer
}
}

function processLine(line) { // here's where we do something with a line

if (line[line.length-1] == '\r') line=line.substr(0,line.length-1); // discard CR (0x0D)

if (line.length > 0) { // ignore empty lines
var obj = JSON.parse(line); // parse the JSON
console.log(obj); // do something with the data here!
}
}

每次文件流从文件系统接收数据时,都会将其存储在缓冲区中,然后调用pump

如果缓冲区中没有换行符,pump 只是返回而不执行任何操作。下次流获取数据时,更多数据(可能还有换行符)将被添加到缓冲区,然后我们将拥有一个完整的对象。

如果有换行符,pump 将从开头到换行符的缓冲区切掉,并将其交给 process。然后它再次检查缓冲区中是否有另一个换行符(while 循环)。这样,我们就可以处理当前 block 中读取的所有行。

最后,每个输入行都会调用一次process。如果存在,它会去掉回车符(以避免行结尾问题 - LF 与 CRLF),然后调用该行中的 JSON.parse 。此时,您可以对对象执行任何您需要的操作。

请注意,JSON.parse 对于它接受的输入内容非常严格;您必须用双引号将标识符和字符串值括起来。换句话说,{name:'thing1'}会抛出错误;您必须使用{"name":"thing1"}

因为内存中一次最多只有一大块数据,所以这将非常高效地内存。它也将非常快。快速测试显示我在 15 毫秒内处理了 10,000 行。

关于javascript - 在 Nodejs 中解析大型 JSON 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44991244/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com