[英]How to append arrays to existing json array and write to file in node js
[英]How to append to a file in Node?
我正在尝试将字符串附加到日志文件中。 但是 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'
知道如何以简单的方式做到这一点吗?
当您想写入日志文件时,即将数据附加到文件末尾,切勿使用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
,因此您的文件将在您的进程结束时结束并且您避免打开太多文件。
您使用 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
,您还可以在writeFile
传递一个标志以将数据附加到现有文件。
fs.writeFile('log.txt', 'Hello Node', {'flag':'a'}, function(err) {
if (err) {
return console.error(err);
}
});
通过传递标志'a',数据将被附加到文件的末尾。
您需要打开它,然后写入。
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方法。
使用a+
标志附加并创建一个文件(如果不存在):
fs.writeFile('log.txt', 'Hello Node', { flag: "a+" }, (err) => {
if (err) throw err;
console.log('The file is created if not existing!!');
});
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!');
});
我的方法比较特殊。 我基本上使用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
将在下一个滴答中将数据刷新到文件中。
在我的场景中,各种大小的峰值高达每秒约 200 次写入。 然而,在夜间,每分钟只需要少量写入。 即使在高峰时段,该代码也能非常可靠地工作。
当您需要将某些内容附加到文件时,使用fs.appendFile
或fsPromises.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.'
);
})();
如果您想要一种简单无压力的方式在文件中逐行写入日志,那么我推荐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 测试。
fd = fs.openSync(path.join(process.cwd(), 'log.txt'), 'a')
fs.writeSync(fd, 'contents to append')
fs.closeSync(fd)
使用jfile包:
myFile.text+='\nThis is new line to be appended'; //myFile=new JFile(path);
我提供这个建议只是因为对打开标志的控制有时很有用,例如,您可能希望首先将其截断为现有文件,然后向其附加一系列写入 - 在这种情况下,在打开文件时使用“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!');
});
});
});
尝试使用flags: 'a'
将数据附加到文件
var stream = fs.createWriteStream("udp-stream.log", {'flags': 'a'});
stream.once('open', function(fd) {
stream.write(msg+"\r\n");
});
这是一个完整的脚本。 填写您的文件名并运行它,它应该可以工作! 这是有关脚本背后逻辑的视频教程。
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);
一个更简单的方法是
const fs = require('fs');
fs.appendFileSync('file.txt', 'message to append into 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');
}
除了denysonique 的 answer 之外,有时在appendFile
中使用异步类型的appendFile
和其他异步方法,其中 promise 返回而不是回调传递。 为此,您需要使用promisify
HOF 包装函数或从 promises 命名空间导入异步函数:
const { appendFile } = require('fs').promises;
await appendFile('path/to/file/to/append', dataToAppend, optionalOptions);
我希望它会有所帮助😉
我将 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);
}
});
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.