如何在 Node 中追加到文件?

发布于 2024-09-13 17:40:01 字数 275 浏览 5 评论 0原文

我正在尝试将字符串附加到日志文件中。但是 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'

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

I am trying to append a string to a log file. However writeFile will erase the content each time before writing the string.

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

Any idea how to do this the easy way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(18

愁杀 2024-09-20 17:40:01

对于偶尔的追加,您可以使用 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');

但是,如果您重复追加到同一个文件,最好 重用文件句柄

For occasional appends, you can use appendFile, which creates a new file handle each time it's called:

Asynchronously:

const fs = require('fs');

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

Synchronously:

const fs = require('fs');

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

But if you append repeatedly to the same file, it's much better to reuse the file handle.

影子是时光的心 2024-09-20 17:40:01

当您想要写入日志文件(即将数据附加到文件末尾)时,切勿使用appendFileappendFile 为添加到文件中的每条数据打开一个文件句柄,过了一会儿,您会收到一个漂亮的 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,因此您的文件将在进程结束时结束,并且避免打开太多文件。

When you want to write in a log file, i.e. appending data to the end of a file, never use appendFile. appendFile opens a file handle for each piece of data you add to your file, after a while you get a beautiful EMFILE error.

I can add that appendFile is not easier to use than a WriteStream.

Example with 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());

Up to 8000 on my computer, you can append data to the file, then you obtain this:

{ 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' }

Moreover, appendFile will write when it is enabled, so your logs will not be written by timestamp. You can test with example, set 1000 in place of 100000, order will be random, depends on access to file.

If you want to append to a file, you must use a writable stream like this:

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();

You end it when you want. You are not even required to use stream.end(), default option is AutoClose:true, so your file will end when your process ends and you avoid opening too many files.

纵情客 2024-09-20 17:40:01

使用 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');

Your code using createWriteStream creates a file descriptor for every write. log.end is better because it asks node to close immediately after the write.

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');
月野兔 2024-09-20 17:40:01

使用 a+ 标志追加创建文件(如果不存在):

fs.writeFile('log.txt', 'Hello Node', { flag: "a+" }, (err) => {
  if (err) throw err;
  console.log('The file is created if not existing!!');
}); 

文档:https://nodejs.org/api/fs.html#fs_file_system_flags

Use a+ flag to append and create a file (if doesn't exist):

fs.writeFile('log.txt', 'Hello Node', { flag: "a+" }, (err) => {
  if (err) throw err;
  console.log('The file is created if not existing!!');
}); 

Docs: https://nodejs.org/api/fs.html#fs_file_system_flags

ゞ记忆︶ㄣ 2024-09-20 17:40:01

除了appendFile之外,您还可以在writeFile中传递一个标志来将数据追加到现有文件中。

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

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

Besides appendFile, you can also pass a flag in writeFile to append data to an existing file.

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

By passing flag 'a', data will be appended at the end of the file.

╄→承喏 2024-09-20 17:40:01

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

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');
    });
  });
});

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

open
写入
关闭


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

You need to open it, then write to it.

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');
    });
  });
});

Here's a few links that will help explain the parameters

open
write
close


EDIT: This answer is no longer valid, look into the new fs.appendFile method for appending.

飘然心甜 2024-09-20 17:40:01

当您需要向文件追加内容时,使用 fs.appendFilefsPromises.appendFile 是最快且最可靠的选项。

与建议的一些答案相反,如果将文件路径提供给 appendFile 函数,它实际上会自行关闭。仅当您传递通过 fs.open() 等方式获得的文件句柄时,您才必须注意关闭它。

我在一个文件中尝试了超过 50,000 行。

示例 :

(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.'
  );
})();

enter此处的图像描述

参考:https://github.com/nodejs/node/问题/7560

Using fs.appendFile or fsPromises.appendFile are the fastest and the most robust options when you need to append something to a file.

In contrast to some of the answers suggested, if the file path is supplied to the appendFile function, It actually closes by itself. Only when you pass in a filehandle that you get by something like fs.open() you have to take care of closing it.

I tried it with over 50,000 lines in a file.

Examples :

(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.'
  );
})();

enter image description here

Ref: https://github.com/nodejs/node/issues/7560

万水千山粽是情ミ 2024-09-20 17:40:01

我的做法比较特别。我基本上使用 WriteStream 解决方案,但没有使用 stream.end() 实际上“关闭”fd。相反,我使用cork/uncork。这具有低 RAM 使用率的好处(如果这对任何人都很重要),并且我相信用于日志记录/记录(我最初的用例)更安全。

下面是一个非常简单的例子。请注意,我刚刚为展示添加了一个伪 for 循环——在生产代码中我正在等待 websocket 消息。

var stream = fs.createWriteStream("log.txt", {flags:'a'});
for(true) {
  stream.cork();
  stream.write("some content to log");
  process.nextTick(() => stream.uncork());
}

uncork 将在下一个tick中将数据刷新到文件中。

在我的场景中,各种大小的写入峰值可达每秒约 200 次。然而,在夜间,每分钟只需要少量写入。即使在高峰时段,该代码也运行得非常可靠。

My approach is rather special. I basically use the WriteStream solution but without actually 'closing' the fd by using stream.end(). Instead I use cork/uncork. This got the benefit of low RAM usage (if that matters to anyone) and I believe it's more safe to use for logging/recording (my original use case).

Following is a pretty simple example. Notice I just added a pseudo for loop for showcase -- in production code I am waiting for websocket messages.

var stream = fs.createWriteStream("log.txt", {flags:'a'});
for(true) {
  stream.cork();
  stream.write("some content to log");
  process.nextTick(() => stream.uncork());
}

uncork will flush the data to the file in the next tick.

In my scenario there are peaks of up to ~200 writes per second in various sizes. During night time however only a handful writes per minute are needed. The code is working super reliable even during peak times.

生生漫 2024-09-20 17:40:01

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!');
});

文档< /a>

Node.js 0.8 has fs.appendFile:

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

Documentation

灼疼热情 2024-09-20 17:40:01

如果您想要一种简单、无压力的方式在文件中逐行写入日志,那么我推荐 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 进行测试。

If you want an easy and stress-free way to write logs line by line in a file, then I recommend 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');

Tested with Node v8.9.4.

忱杏 2024-09-20 17:40:01
fd = fs.openSync(path.join(process.cwd(), 'log.txt'), 'a')
fs.writeSync(fd, 'contents to append')
fs.closeSync(fd)
fd = fs.openSync(path.join(process.cwd(), 'log.txt'), 'a')
fs.writeSync(fd, 'contents to append')
fs.closeSync(fd)
幸福丶如此 2024-09-20 17:40:01

我提供此建议只是因为对打开标志的控制有时很有用,例如,您可能希望首先将其截断为现有文件,然后然后向其追加一系列写入 - 在这种情况下使用 '打开文件时使用 w' 标志,并且在所有写入完成之前不要关闭它。当然,appendFile 可能就是您想要的:-)

  fs.open('log.txt', 'a', function(err, log) {
    if (err) throw err;
    fs.writeFile(log, 'Hello Node', function (err) {
      if (err) throw err;
      fs.close(log, function(err) {
        if (err) throw err;
        console.log('It\'s saved!');
      });
    });
  });

I offer this suggestion only because control over open flags is sometimes useful, for example, you may want to truncate it an existing file first and then append a series of writes to it - in which case use the 'w' flag when opening the file and don't close it until all the writes are done. Of course appendFile may be what you're after :-)

  fs.open('log.txt', 'a', function(err, log) {
    if (err) throw err;
    fs.writeFile(log, 'Hello Node', function (err) {
      if (err) throw err;
      fs.close(log, function(err) {
        if (err) throw err;
        console.log('It\'s saved!');
      });
    });
  });
陪我终i 2024-09-20 17:40:01

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

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

Try to use flags: 'a' to append data to a file

 var stream = fs.createWriteStream("udp-stream.log", {'flags': 'a'});
  stream.once('open', function(fd) {
    stream.write(msg+"\r\n");
  });
渔村楼浪 2024-09-20 17:40:01

使用 jfile 包:

myFile.text+='\nThis is new line to be appended'; //myFile=new JFile(path);

Using jfile package :

myFile.text+='\nThis is new line to be appended'; //myFile=new JFile(path);
韶华倾负 2024-09-20 17:40:01

这是一个完整的脚本。填写您的文件名并运行它,它应该可以工作!
这是有关脚本背后逻辑的视频教程

var fs = require('fs');

function ReadAppend(file, appendFile){
  fs.readFile(appendFile, function (err, data) {
    if (err) throw err;
    console.log('File was read');

    fs.appendFile(file, data, function (err) {
      if (err) throw err;
      console.log('The "data to append" was appended to file!');

    });
  });
}
// edit this with your file names
file = 'name_of_main_file.csv';
appendFile = 'name_of_second_file_to_combine.csv';
ReadAppend(file, appendFile);

Here's a full script. Fill in your file names and run it and it should work!
Here's a video tutorial on the logic behind the script.

var fs = require('fs');

function ReadAppend(file, appendFile){
  fs.readFile(appendFile, function (err, data) {
    if (err) throw err;
    console.log('File was read');

    fs.appendFile(file, data, function (err) {
      if (err) throw err;
      console.log('The "data to append" was appended to file!');

    });
  });
}
// edit this with your file names
file = 'name_of_main_file.csv';
appendFile = 'name_of_second_file_to_combine.csv';
ReadAppend(file, appendFile);
梦萦几度 2024-09-20 17:40:01
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');
}
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');
}
云归处 2024-09-20 17:40:01

除了denysonique的回答之外,有时还会使用异步类型的appendFile以及NodeJS中的其他异步方法其中 Promise 返回而不是回调传递。为此,您需要使用 promisify HOF 包装函数或从 Promise 命名空间导入异步函数:

const { appendFile } = require('fs').promises;

await appendFile('path/to/file/to/append', dataToAppend, optionalOptions);

我希望它会有所帮助

In addition to denysonique's answer, sometimes asynchronous type of appendFile and other async methods in NodeJS are used where promise returns instead of callback passing. To do it you need to wrap the function with promisify HOF or import async functions from promises namespace:

const { appendFile } = require('fs').promises;

await appendFile('path/to/file/to/append', dataToAppend, optionalOptions);

I hope it'll help ????

你另情深 2024-09-20 17:40:01

我将 async fs.appendFile 包装到基于 Promise 的函数中。希望它可以帮助其他人了解这是如何运作的。

    append (path, name, data) {

        return new Promise(async (resolve, reject) => {

            try {

                fs.appendFile((path + name), data, async (err) => {

                    if (!err) {

                        return resolve((path + name));

                    } else {

                        return reject(err);

                    }

                });

            } catch (err) {

                return reject(err);

            }

        });

    }

I wrapped the async fs.appendFile into a Promise-based function. Hope it helps others to see how this would work.

    append (path, name, data) {

        return new Promise(async (resolve, reject) => {

            try {

                fs.appendFile((path + name), data, async (err) => {

                    if (!err) {

                        return resolve((path + name));

                    } else {

                        return reject(err);

                    }

                });

            } catch (err) {

                return reject(err);

            }

        });

    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文