Node.js 使用nodejs从文件中删除最后n行

Node.js 使用nodejs从文件中删除最后n行,node.js,fs,Node.js,Fs,我正在尝试使用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

我正在尝试使用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);

    });
});

让我们创建一个大文件:

$ 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
$ time node c.js
File truncated!
node c.js  0.14s user 0.04s system 8% cpu 2.022 total
我的代码使用,它不读取整个文件,它寻找到最后,然后向后读取块,直到达到预期的行数,然后以正确的方向显示行,直到文件结束。现在我知道要消失的字节数。然后我使用,它告诉我文件中的总字节数。现在,在删除最后的
n
行之后,我知道了文件末尾实际需要多少字节。最后,我使用了,这将导致常规文件被截断为指定给它的大小(以字节为单位)

更新:

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

$ 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 b.js
File truncated!
node b.js  0.07s user 0.03s system 6% cpu 1.542 total
$ 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作为我的主要平台,但我知道并不是所有人都这么做,所以我总是考虑在任何地方都适用的解决方案。