我试图追加一个字符串到日志文件。但是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'

有什么简单的方法吗?


当前回答

如果你想要一种简单而无压力的方法在文件中逐行写入日志,那么我推荐fs-extra:

const os = require('os');
const fs = require('fs-extra');

const file = 'logfile.txt';
const options = {flag: 'a'};

async function writeToFile(text) {
  await fs.outputFile(file, `${text}${os.EOL}`, options);
}

writeToFile('First line');
writeToFile('Second line');
writeToFile('Third line');
writeToFile('Fourth line');
writeToFile('Fifth line');

使用Node v8.9.4测试。

其他回答

当你想写入日志文件时,也就是在文件末尾追加数据时,永远不要使用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,所以你的文件将在你的进程结束时结束,你可以避免打开太多文件。

Node.js 0.8有fs.appendFile:

fs.appendFile('message.txt', 'data to append', (err) => {
  if (err) throw err;
  console.log('The "data to append" was appended to file!');
});

文档

const inovioLogger = (logger = "") => {
    const log_file = fs.createWriteStream(__dirname + `/../../inoviopay-${new Date().toISOString().slice(0, 10)}.log`, { flags: 'a' });
    const log_stdout = process.stdout;
    log_file.write(logger + '\n');
}

使用fs。appendFile或fsPromises。当您需要向文件中追加内容时,appendFile是最快和最健壮的选项。

与建议的一些答案相反,如果文件路径提供给appendFile函数,它实际上会自行关闭。只有传入fs.open()之类的文件句柄时,才需要注意关闭它。

我在一个超过5万行的文件中试过。

例子:

(async () => {
  // using appendFile.
  const fsp = require('fs').promises;
  await fsp.appendFile(
    '/path/to/file', '\r\nHello world.'
  );

  // using apickfs; handles error and edge cases better.
  const apickFileStorage = require('apickfs');
  await apickFileStorage.writeLines(
    '/path/to/directory/', 'filename', 'Hello world.'
  );
})();

裁判:https://github.com/nodejs/node/issues/7560

尝试使用flags: 'a'将数据附加到文件中

 var stream = fs.createWriteStream("udp-stream.log", {'flags': 'a'});
  stream.once('open', function(fd) {
    stream.write(msg+"\r\n");
  });