如何附加到节点中的文件?

IT技术 javascript node.js fs appendfile
2021-02-07 23:56:34

我正在尝试字符串附加到日志文件中。但是 writeFile 每次写入字符串之前都会擦除内容。

fs.writeFile('log.txt', 'Hello Node', function (err) {
  if (err) throw err;
  console.log('It\'s saved!');
}); // => message.txt erased, contains only 'Hello Node'

知道如何以简单的方式做到这一点吗?

6个回答

对于偶尔的追加,您可以使用appendFile,它会在每次调用时创建一个新的文件句柄:

异步

const fs = require('fs');

fs.appendFile('message.txt', 'data to append', function (err) {
  if (err) throw err;
  console.log('Saved!');
});

同步

const fs = require('fs');

fs.appendFileSync('message.txt', 'data to append');

但是如果你重复追加到同一个文件,重用文件句柄会好得多

以防万一:请注意,这是异步的。这可能会导致奇怪的时间安排和其他事情。例如:如果您process.exit()刚刚在 之后fs.appendFile,您可以在输出发送之前退出。(使用没问题return。)
2021-03-14 23:56:34
@nelsonic 根据源码,没有特别处理。
2021-03-16 23:56:34
@chrisdew 感谢您的更新……但是……如果我们不在这里使用已接受的答案,我们应该怎么做?你是如何解决这个困境的?
2021-04-01 23:56:34
更糟糕的情况是,您可以使用同步版本appendFileSync. nodejs.org/api/...但是你可能会失去 Node 的一大好处,那就是异步操作。确保您发现错误。也许在某些操作系统上,如果同时请求文件句柄,您可能会拒绝访问。不确定。
2021-04-02 23:56:34
有谁知道fs.appendFile是否保持打开文件的链接以便追加更快?(而不是打开/关闭每次写入)nodejs.org/api/...
2021-04-04 23:56:34

当您想写入日志文件时,即将数据附加到文件末尾时,切勿使用appendFile. appendFile为您添加到文件中的每条数据打开一个文件句柄,一段时间后您会收到一个漂亮的EMFILE错误。

我可以补充一点,appendFile它并不比WriteStream.

示例appendFile

console.log(new Date().toISOString());
[...Array(10000)].forEach( function (item,index) {
    fs.appendFile("append.txt", index+ "\n", function (err) {
        if (err) console.log(err);
    });
});
console.log(new Date().toISOString());

在我的电脑上最多8000个,你可以将数据附加到文件中,然后你得到这个:

{ Error: EMFILE: too many open files, open 'C:\mypath\append.txt'
    at Error (native)
  errno: -4066,
  code: 'EMFILE',
  syscall: 'open',
  path: 'C:\\mypath\\append.txt' }

此外,appendFile启用时会写入,因此您的日志不会按时间戳写入。您可以通过示例进行测试,设置 1000 代替 100000,顺序将是随机的,取决于对文件的访问。

如果要附加到文件,则必须使用像这样的可写流:

var stream = fs.createWriteStream("append.txt", {flags:'a'});
console.log(new Date().toISOString());
[...Array(10000)].forEach( function (item,index) {
    stream.write(index + "\n");
});
console.log(new Date().toISOString());
stream.end();

你在你想要的时候结束它。您甚至不需要使用stream.end(),默认选项是AutoClose:true,因此您的文件将在您的进程结束时结束,并且您可以避免打开太多文件。

due to asynchronous nature of Javascript... 什么?Array.forEach 是一个同步操作。JS 是同步的。它恰好提供了一些管理异步操作的方法,比如 Promises 和 async/await。
2021-03-15 23:56:34
我猜会fs.appendFile导致打开的文件太多,因为您以异步方式执行它(您只是异步创建 10000 个文件句柄),我相信appendFileSync不会有类似的问题,也不会有fs.appendFile适当的间隔(1s 可能绰绰有余)或排队。
2021-03-30 23:56:34
@RedwolfPrograms 对于繁忙的服务器日志,可能是真的。对于每个执行日志一次,也许不是。无论如何,我只是声明这个答案中的观点(至少是原因)是不正确的。
2021-04-01 23:56:34
@appleapple 但是您每次仍然打开文件。对于日志,保持打开状态更有意义。
2021-04-04 23:56:34
感谢您的出色回答,但我的疑问是,由于 Javascript 的异步性质,它将在stream.end()之前执行stream.write(),所以我们不应该使用stream.end(),正如您提到的,这AutoClose:True是一个默认选项,那么为什么还要写一行没有利用。
2021-04-06 23:56:34

您使用 createWriteStream 的代码为每次写入创建一个文件描述符。log.end 更好,因为它要求节点在写入后立即关闭。

var fs = require('fs');
var logStream = fs.createWriteStream('log.txt', {flags: 'a'});
// use {flags: 'a'} to append and {flags: 'w'} to erase and write a new file
logStream.write('Initial line...');
logStream.end('this is the end line');
缺少第一行!应该是 'var fs = require('fs');'
2021-03-19 23:56:34
虽然初始行和结束行都在同一行上:-p
2021-03-20 23:56:34
请注意:如果您正在使用fs.createWriteStream,则使用flags. 如果您正在使用,fs.writeFile那么它是flag. 请参阅Node JS Docs - File System了解更多信息。
2021-03-20 23:56:34
或者甚至更好var fs = require('graceful-fs'),它解决了一些已知问题。有关更多信息,请参阅文档
2021-03-21 23:56:34
@BennyNeugebauer 使用标志是正确的,你不是。它已经在您将文档链接到 fs.writeFile 之前发布了几个月,它确实使用了“标志”。但是这个解决方案使用 fs.createWriteStream 并且参数“flags”是正确的 - nodejs.org/api/fs.html#fs_fs_createwritestream_path_options
2021-03-22 23:56:34

此外appendFile,您还可以传入一个标志writeFile以将数据附加到现有文件中。

fs.writeFile('log.txt', 'Hello Node',  {'flag':'a'},  function(err) {
    if (err) {
        return console.error(err);
    }
});

通过传递标志'a',数据将被附加到文件的末尾。

请注意:如果您正在使用fs.createWriteStream,则使用flags. 如果您正在使用,fs.writeFile那么它是flag. 请参阅Node JS Docs - File System了解更多信息。
2021-04-04 23:56:34

您需要打开它,然后写入。

var fs = require('fs'), str = 'string to append to file';
fs.open('filepath', 'a', 666, function( e, id ) {
  fs.write( id, 'string to append to file', null, 'utf8', function(){
    fs.close(id, function(){
      console.log('file closed');
    });
  });
});

这是一些有助于解释参数的链接

打开

关闭


编辑:此答案不再有效,请查看用于追加的新fs.appendFile方法。

看起来像supercobra不断地将日志写入日志文件,在这种情况下不推荐使用fs.write,而是使用fs.createWriteStream。阅读nodejs.org/docs/v0.4.8/api/all.html#fs.write
2021-03-13 23:56:34
它应该是“0666”而不是 666。
2021-03-15 23:56:34
从 nodejs v0.4.10 开始,答案不再准确。
2021-04-06 23:56:34