簡體   English   中英

在 Node.JS 中一次讀取 N 行大文件

[英]Read a large file N lines at a time in Node.JS

我有一個包含 65,000,000 行的文件,大小約為 2GB。

我想一次在 N 行中讀取這個文件,執行一個 db 插入操作,然后讀取下一個 N,在這種情況下,N 是 1000。 插入順序無關緊要,所以同步就可以了。

這樣做的最佳方法是什么? 我只發現一次加載 1 行,或者將整個文件讀入內存的方法。 下面的示例代碼,我一直用來一次讀取文件一行。

var singleFileParser = (file, insertIntoDB) => {
    var lr = new LineByLineReader(file);
    lr.on('error', function(err) {
        // 'err' contains error object
        console.error(err);
        console.error("Error reading file!");
    });

    lr.on('line', function(line) {
        insertIntoDB(line);
    // 'line' contains the current line without the trailing newline character.
    });

    lr.on('end', function() {
        // All lines are read, file is closed now.
    });
};

這樣的事情應該做

var cnt = 0;
var tenLines = [];
lr.on('line', function(line) {
    tenLines.push(line);
    if (++cnt >= 10) {
         lr.pause();
         // prepare your SQL statements from tenLines
         dbInsert(<yourSQL>, function(error, returnVal){
            cnt = 0;
            tenLines = [];
            lr.resume();
        });
     }
});

某人一次只能解析一行。 因此,如果您一次想要 10 個,那么您只需一次收集它們,直到收集到 10 個,然后再處理 10 個。

我不認為 Jarek 的代碼工作得很好,所以這里有一個不同的版本,它將 10 行收集到一個數組中,然后調用dbInsert()

var tenLines = [];
lr.on('line', function(line) {
    tenLines.push(line);
    if (tenLines.length === 10) {
        lr.pause();
        dbInsert(<yourSQL>, function(error, returnVal){
            if (error) {
                // some sort of error handling here
            }
            tenLines = [];
            lr.resume();
        });
     }
});
// process last set of lines in the tenLines buffer (if any)
lr.on('end', function() {
    if (tenLines.length !== 0) {
        // process last set of lines
        dbInsert(...);
    }
});

Jarek 的版本似乎在每個line事件上調用dbInsert()而不是每 10 個行事件,並且如果它們不是 10 行長的完美倍數,則不會處理文件末尾的任何剩余行。

這是我在異步函數中的解決方案:

let multipleLines = [];
const filepath = '<file>';
const numberLines = 50;

const lineReader = require('readline').createInterface({
    input: require('fs').createReadStream(filepath)
});

// process lines by numberLines
for await (const line of lineReader) {
    multipleLines.push(line);
    if (multipleLines.length === numberLines) {
        await dbInsert();
        multipleLines = [];
    }
}
// process last set of lines (if any)
if (multipleLines.length !== 0) {
    await dbInsert();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM