【问题标题】:Remove last n lines from file using nodejs使用nodejs从文件中删除最后n行
【发布时间】:2017-07-16 21:49:28
【问题描述】:

我正在尝试使用 fs 作为 nodejs 的一部分从文件中删除最后 3 行。我目前正在将文件读入内存,然后在没有 3 行的情况下再次写入,但我确信有一种更有效的方法不需要将整个文件读入内存。

我现在的代码

fs.readFile(filename, function (err, data) {
    if (err) throw err;
    theFile = data.toString().split("\n");
    theFile.splice(-3, 3);
    fs.writeFile(filename, theFile.join("\n"), function (err) {
        if (err) {
            return console.log(err);
        }
        console.log("Removed last 3 lines");
        console.log(theFile.length);

    });
});

【问题讨论】:

    标签: node.js fs


    【解决方案1】:

    让我们创建一个大文件:

    $ base64 /dev/urandom | head -1000000 > /tmp/crap
    $ wc -l /tmp/crap
    1000000 /tmp/crap
    $ du -sh /tmp/crap
    74M /tmp/crap
    

    这是您的代码:

    $ cat /tmp/a.js
    var fs = require('fs');
    
    var filename = '/tmp/crap1';
    
    fs.readFile(filename, function(err, data) {
        if(err) throw err;
        theFile = data.toString().split("\n");
        theFile.splice(-3,3);
        fs.writeFile(filename, theFile.join("\n"), function(err) {
        if(err) {
            return console.log(err);
        }
        console.log("Removed last 3 lines");
        console.log(theFile.length);
        });
    });
    

    这是我的:

    $ cat /tmp/b.js
    var fs = require('fs'),
        util = require('util'),
        cp = require('child_process');
    
    var filename = '/tmp/crap2';
    var lines2nuke = 3;
    var command = util.format('tail -n %d %s', lines2nuke, filename);
    
    cp.exec(command, (err, stdout, stderr) => {
        if (err) throw err;
        var to_vanquish = stdout.length;
        fs.stat(filename, (err, stats) => {
            if (err) throw err;
            fs.truncate(filename, stats.size - to_vanquish, (err) => {
                if (err) throw err;
                console.log('File truncated!');
            })
        });
    });
    

    让我们复制同一个文件:

    $ cp /tmp/crap /tmp/crap1
    $ cp /tmp/crap /tmp/crap2
    

    让我们看看谁更快:

    $ time node a.js
    Removed last 3 lines
    999998
    node a.js  0.53s user 0.19s system 99% cpu 0.720 total
    
    $ time node b.js
    File truncated!
    node b.js  0.08s user 0.01s system 100% cpu 0.091 total
    

    当我将文件大小增加 10 倍时,我的系统用 a.js 耗尽了内存;但是对于 b.js,它需要:

    $ time node b.js
    File truncated!
    node b.js  0.07s user 0.03s system 6% cpu 1.542 total
    

    我的代码使用tail,它不会读取整个文件,它会寻找到最后,然后向后读取块,直到达到预期的行数,然后它以正确的方向显示行直到结束的文件。现在我现在的字节数消失了。然后我使用fs.stat,它告诉我文件中的总字节数。现在,在删除最后的n 行之后,我知道文件最后需要多少字节。最后,我使用fs.truncate,这会导致常规文件被截断为指定给它的大小(以字节为单位)的精确大小。

    更新:

    OP 说平台是 Windows。在这种情况下,我们可以修改这个程序以调用另一个实用程序,而是在节点本身中执行所有操作。幸运的是,我们已经为我们提供了所需的功能作为节点模块read-last-lines。现在更新后的与操作系统无关的代码如下所示:

    $ npm install read-last-lines
    $ cat /tmp/c.js 
    var fs = require('fs'),
        rll = require('read-last-lines');
    
    var filename = '/tmp/crap2';
    var lines2nuke = 3;
    
    rll.read(filename, lines2nuke).then((lines) => {
        var to_vanquish = lines.length;
        fs.stat(filename, (err, stats) => {
            if (err) throw err;
            fs.truncate(filename, stats.size - to_vanquish, (err) => {
                if (err) throw err;
                console.log('File truncated!');
            })
        });
    });
    

    在 10 倍大小的文件上,它花了:

    $ time node c.js
    File truncated!
    node c.js  0.14s user 0.04s system 8% cpu 2.022 total
    

    【讨论】:

    • 请先生,我得到 'tail' 不是内部或外部命令、可运行程序或批处理文件。。你可以帮帮我吗?在 Win10 上运行节点。谢谢。
    • @statosdotcom 我已经更新了答案,使其也可以在 Windows 上运行。
    • Nehal J Wani,非常感谢。像魅力一样工作。很抱歉浪费您的时间。 +1。上帝保佑。
    • 仅供参考,从一开始就提出多平台解决方案总是好的做法......我也使用 Linux 作为我的主要平台,但我知道并非所有人都这样做,所以我总是考虑可行的解决方案无处不在。
    猜你喜欢
    • 1970-01-01
    • 2012-09-02
    • 1970-01-01
    • 1970-01-01
    • 2018-05-14
    • 2012-11-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多