Ho cercato di trovare un modo per scrivere su un file quando si usa Node.js, ma senza successo. Come posso farlo?
Ci sono molti dettagli nel File System API. Il modo più comune è:
const fs = require('fs');
fs.writeFile("/tmp/test", "Hey there!", function(err) {
if(err) {
return console.log(err);
}
console.log("The file was saved!");
});
Attualmente ci sono tre modi per scrivere un file:
fs.write(fd, buffer, offset, length, position, callback
)
È necessario attendere il callback per assicurarsi che il buffer sia scritto sul disco. Non viene bufferizzato.
fs.writeFile(filename, data, [encoding], callback)
Tutti i dati devono essere memorizzati allo stesso tempo; non è possibile eseguire scritture sequenziali.
fs.createWriteStream(path, [options]
)
Crea un WriteStream
, che è conveniente perché non è necessario attendere un callback. Ma di nuovo, non è bufferizzato.
Un WriteStream
, come dice il nome, è un flusso. Uno stream per definizione è "un buffer" contenente dati che si muovono in una direzione (sorgente ► destinazione). Ma uno stream scrivibile non è necessariamente "bufferato". Uno stream è "bufferizzato" quando si scrive n
volte, e al tempo n+1
, lo stream invia il buffer al kernel (perché è pieno e deve essere lavato).
In altre parole: "Un buffer" è l'oggetto. Che sia "bufferato" o meno è una proprietà di quell'oggetto.
Se guardate il codice, il WriteStream
eredita da un oggetto Stream
scrivibile. Se fai attenzione, vedrai come fanno il flush del contenuto; non hanno nessun sistema di buffering.
Se scrivi una stringa, viene convertita in un buffer, e poi inviata al livello nativo e scritta su disco. Quando si scrivono stringhe, non riempiono nessun buffer. Quindi, se lo fai:
-- language-all: lang-js -->
write("a")
write("b")
write("c")
Stai facendo:
fs.write(new Buffer("a"))
fs.write(new Buffer("b"))
fs.write(new Buffer("c"))
Sono tre chiamate al livello I/O. Anche se stai usando dei "buffer", i dati non sono bufferizzati. Un flusso bufferizzato farebbe: fs.write(new Buffer ("abc"))
, una chiamata al livello I/O.
A partire da ora, in Node.js v0.12 (versione stabile annunciata 02/06/2015) ora supporta due funzioni:
cork()
e
uncork()
. Sembra che queste funzioni permetteranno finalmente di bufferizzare/flushare le chiamate di scrittura.
Per esempio, in Java ci sono alcune classi che forniscono flussi bufferizzati (BufferedOutputStream
, BufferedWriter
...). Se si scrivono tre byte, questi byte saranno immagazzinati nel buffer (memoria) invece di fare una chiamata I/O solo per tre byte. Quando il buffer è pieno, il contenuto viene lavato e salvato su disco. Questo migliora le prestazioni.
Non sto scoprendo nulla, sto solo ricordando come dovrebbe essere fatto un accesso al disco.
Naturalmente è possibile renderlo un po' più avanzato. Non-bloccando, scrivendo bit e pezzi, non scrivendo tutto il file in una volta:
var fs = require('fs');
var stream = fs.createWriteStream("my_file.txt");
stream.once('open', function(fd) {
stream.write("My first row\n");
stream.write("My second row\n");
stream.end();
});