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

时间:2017-02-26 08:02:19

标签: 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(filename, theFile.join("\n"), function (err) {
        if (err) {
            return console.log(err);
        }
        console.log("Removed last 3 lines");
        console.log(theFile.length);

    });
});

1 个答案:

答案 0 :(得分:9)

让我们创建一个巨大的文件:

$ 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。在这种情况下,我们可以将此程序修改为 not 调用另一个实用程序,但在节点本身中执行所有操作。幸运的是,作为节点模块read-last-lines,我们已经可以使用所需的功能。现在,更新的os不可知代码如下:

$ 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