如何在Node中附加到文件?

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

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

你知道怎么做这个简单的方法吗?

730900 次浏览

你需要打开它,然后写信给它。

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.append文件方法进行附加。

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

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

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

fd = fs.openSync(path.join(process.cwd(), 'log.txt'), 'a')
fs.writeSync(fd, 'contents to append')
fs.closeSync(fd)

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

文档

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

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

我提供这个建议只是因为控制打开标志有时很有用,例如,你可能想先截断一个现有文件,然后然后附加一系列写入-在这种情况下,打开文件时使用'w'标志,直到所有写入完成才关闭它。

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

除了appendFile,您还可以在writeFile中传递标志以将数据附加到现有文件。

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

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

使用jfile包:

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

当您想写入日志文件时,即将数据附加到文件末尾,从未使用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,因此您的文件将在您的流程结束时结束,并且您可以避免打开太多文件。

如果您想要一种简单且无压力的方式在文件中逐行写入日志,那么我推荐fs-额外

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进行测试。

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

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

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


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

希望能帮到😉

当您需要将某些内容附加到文件时,使用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.'
);
})();

在此处输入图片描述

参考:https://github.com/nodejs/node/issues/7560

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

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

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

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

在我的场景中,每秒有高达200次写入的峰值,大小不一。然而,在夜间,每分钟只需要少量写入。即使在高峰时间,代码也工作得非常可靠。

我将asyncfs.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);


}


});


}

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

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

使用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