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