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

我试图从文件中删除最后3行使用fs作为nodejs的一部分。 我目前正在读取文件到内存中,然后再次写入没有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); }); }); 

我们来创build一个巨大的文件:

 $ 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 ,它不读取整个文件,它寻find最后,然后读取块,直到达到预期的行数,然后它显示在正确的方向,直到文件的结尾的行。 现在我现在要消失的字节数。 然后我使用fs.stat ,它告诉我文件中的总字节数。 现在,我知道在最后的n行删除后,我在文件中实际需要多less字节。 最后,我使用fs.truncate ,这会导致常规文件被截断为指定的大小(以字节为单位)。

更新:

OP说这个平台是Windows。 在这种情况下,我们可以修改这个程序来调用另一个实用程序,而是在节点本身做所有事情。 幸运的是,所需的function已经作为节点模块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