Hoe toe te voegen aan een bestand in Node?

Ik probeer een string toe te voegenaan een logbestand. WriteFile zal de inhoud echter elke keer wissen voordat de tekenreeks wordt geschreven.

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

Enig idee hoe je dit op een makkelijke manier kunt doen?


Antwoord 1, autoriteit 100%

Voor incidentele toevoegingen kunt u appendFilegebruiken, dat elke keer dat het wordt aangeroepen een nieuwe bestandshandle aanmaakt:

Asynchroon:

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

Synchroon:

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

Maar als je herhaaldelijk aan hetzelfde bestand toevoegt, is het veel beter om gebruik de bestandshandle.


Antwoord 2, autoriteit 32%

Als je in een logbestand wilt schrijven, d.w.z. gegevens aan het einde van een bestand wilt toevoegen, nooitgebruik dan appendFile. appendFileopent een bestandshandle voor elk stukje gegevens dat u aan uw bestand toevoegt, na een tijdje krijgt u een mooie EMFILE-foutmelding.

Ik kan hieraan toevoegen dat appendFileniet gemakkelijker te gebruiken is dan een WriteStream.

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

Tot 8000 op mijn computer, je kunt gegevens aan het bestand toevoegen, dan krijg je dit:

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

Bovendien zal appendFileschrijven wanneer het is ingeschakeld, dus uw logboeken worden niet op tijdstempel geschreven. U kunt testen met bijvoorbeeld 1000 instellen in plaats van 100000, de volgorde is willekeurig, afhankelijk van de toegang tot het bestand.

Als je iets aan een bestand wilt toevoegen, moeteen schrijfbare stream als deze gebruiken:

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

Je beëindigt het wanneer je wilt. U bent niet eens verplicht om stream.end()te gebruiken, de standaardoptie is AutoClose:true, dus uw bestand eindigt wanneer uw proces eindigt en u voorkomt dat u te veel bestanden opent .


Antwoord 3, autoriteit 14%

Uw code die gebruikmaakt van createWriteStream creëert een bestandsdescriptor voor elke schrijfactie. log.end is beter omdat het knooppunt vraagt om onmiddellijk na het schrijven te sluiten.

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

Antwoord 4, autoriteit 3%

Naast appendFile, kunt u ook een vlag doorgeven in writeFileom gegevens toe te voegen aan een bestaand bestand.

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

Door vlag ‘a’ door te geven, worden gegevens aan het einde van het bestand toegevoegd.


Antwoord 5, autoriteit 2%

Je moet het openen en er vervolgens naar schrijven.

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

Hier zijn een paar links die helpen bij het uitleggen van de parameters

openen
schrijven
sluiten


EDIT: dit antwoord is niet langer geldig, kijk in de nieuwe fs.appendFilemethode om toe te voegen.


Antwoord 6

Node.js 0.8 heeft fs.appendFile:

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

Documentatie


Antwoord 7

Mijn aanpak is nogal bijzonder. Ik gebruik eigenlijk de WriteStream-oplossing, maar zonder de fd daadwerkelijk te ‘sluiten’ door stream.end()te gebruiken. In plaats daarvan gebruik ik cork/uncork. Dit kreeg het voordeel van een laag RAM-gebruik (als dat voor iemand van belang is) en ik geloof dat het veiliger is om te gebruiken voor logboekregistratie / opname (mijn oorspronkelijke gebruiksgeval).

Het volgende is een vrij eenvoudig voorbeeld. Merk op dat ik zojuist een pseudo for-lus voor showcase heb toegevoegd — in productiecode wacht ik op websocket-berichten.

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

uncorkspoelt de gegevens naar het bestand bij de volgende tik.

In mijn scenario zijn er pieken tot ~200 schrijfbewerkingen per seconde in verschillende groottes. Tijdens de nacht zijn er echter slechts een handvol schrijfacties per minuut nodig. De code werkt super betrouwbaar, zelfs tijdens piekuren.


Antwoord 8

Gebruik a+vlag om toe te voegenen maakeen bestand (als het niet bestaat):

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

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


Antwoord 9

Als je een gemakkelijke en stressvrije manier wilt om logs regel voor regel in een bestand te schrijven, dan raad ik 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');

Getest met Node v8.9.4.


Antwoord 10

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

Antwoord 11

Het gebruik van fs.appendFileof fsPromises.appendFilezijn de snelste en meest robuuste opties wanneer u iets aan een bestand moet toevoegen.

In tegenstelling tot sommige van de voorgestelde antwoorden, als het bestandspad wordt geleverd aan de functie appendFile, het sluit eigenlijk vanzelf. Alleen als je een filehandle doorgeeft die je krijgt door zoiets als fs.open(), moet je ervoor zorgen dat deze wordt gesloten.

Ik heb het geprobeerd met meer dan 50.000 regels in een bestand.

Voorbeelden:

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

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


12

JFile pakket:

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

13

Probeer flags: 'a'om gegevens aan een bestand toe te voegen

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

14

Hier is een volledig script. Vul uw bestandsnamen in en voer het uit en het moet werken!
Hier is een video-tutorial op de logica achter het 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);

15

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

16

Naast Denysonique’s antwoord , soms asynchrone type appendFileen andere async-methoden in Nodejs worden gebruikt waar belofte retourneert in plaats van callback passeren. Om het te doen, moet u de functie inpakken met promisifyHOF of IMPORT ASYNC-functies van beloftes NAMEESPACE:

const { appendFile } = require('fs').promises;
await appendFile('path/to/file/to/append', dataToAppend, optionalOptions);

Ik hoop dat het helpt 😉


Antwoord 17

Ik heb de asynchrone fs.appendFile in een op Promise gebaseerde functie verpakt. Ik hoop dat het anderen helpt om te zien hoe dit zou werken.

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

Other episodes