Node.js
File system I / O
Ricerca…
Osservazioni
In Node.js, le operazioni intensive come l'I / O vengono eseguite in modo asincrono , ma hanno una controparte sincrona (es. Esiste un file fs.readFile
e la sua controparte è fs.readFileSync
). Poiché il nodo è a thread singolo, è necessario prestare attenzione quando si utilizzano le operazioni sincrone , poiché bloccano l'intero processo.
Se un processo è bloccato da un'operazione sincrona, viene interrotto l'intero ciclo di esecuzione (incluso il ciclo degli eventi). Ciò significa che non verranno eseguiti altri codici asincroni, inclusi eventi e gestori di eventi, e il programma continuerà ad attendere fino al completamento dell'operazione di blocco singolo.
Vi sono usi appropriati sia per le operazioni sincrone che asincrone, ma occorre fare attenzione che vengano utilizzati correttamente.
Scrivere su un file usando writeFile o writeFileSync
var fs = require('fs');
// Save the string "Hello world!" in a file called "hello.txt" in
// the directory "/tmp" using the default encoding (utf8).
// This operation will be completed in background and the callback
// will be called when it is either done or failed.
fs.writeFile('/tmp/hello.txt', 'Hello world!', function(err) {
// If an error occurred, show it and return
if(err) return console.error(err);
// Successfully wrote to the file!
});
// Save binary data to a file called "binary.txt" in the current
// directory. Again, the operation will be completed in background.
var buffer = new Buffer([ 0x48, 0x65, 0x6c, 0x6c, 0x6f ]);
fs.writeFile('binary.txt', buffer, function(err) {
// If an error occurred, show it and return
if(err) return console.error(err);
// Successfully wrote binary contents to the file!
});
fs.writeFileSync
comporta in modo simile a fs.writeFile
, ma non fs.writeFile
una richiamata poiché completa in modo sincrono e quindi blocca il thread principale. La maggior parte degli sviluppatori di node.js preferiscono le varianti asincrone che non causeranno praticamente alcun ritardo nell'esecuzione del programma.
Nota: il blocco del thread principale è una pratica scorretta in node.js. La funzione sincrona deve essere utilizzata solo durante il debug o quando non sono disponibili altre opzioni.
// Write a string to another file and set the file mode to 0755
try {
fs.writeFileSync('sync.txt', 'anni', { mode: 0o755 });
} catch(err) {
// An error occurred
console.error(err);
}
Leggi in modo asincrono dai file
Usa il modulo del filesystem per tutte le operazioni sui file:
const fs = require('fs');
Con codifica
In questo esempio, leggi hello.txt
dalla directory /tmp
. Questa operazione sarà completata in background e il callback si verifica al completamento o al fallimento:
fs.readFile('/tmp/hello.txt', { encoding: 'utf8' }, (err, content) => {
// If an error occurred, output it and return
if(err) return console.error(err);
// No error occurred, content is a string
console.log(content);
});
Senza codifica
Leggi il file binary.txt
binario dalla directory corrente, in modo asincrono sullo sfondo. Nota che non impostiamo l'opzione 'encoding' - questo impedisce a Node.js di decodificare il contenuto in una stringa:
fs.readFile('binary', (err, binaryContent) => {
// If an error occurred, output it and return
if(err) return console.error(err);
// No error occurred, content is a Buffer, output it in
// hexadecimal representation.
console.log(content.toString('hex'));
});
Percorsi relativi
Tieni presente che, in generale, lo script può essere eseguito con una directory di lavoro corrente arbitraria. Per indirizzare un file relativo allo script corrente, usa __dirname
o __filename
:
fs.readFile(path.resolve(__dirname, 'someFile'), (err, binaryContent) => {
//Rest of Function
}
Elenco dei contenuti della directory con readdir o readdirSync
const fs = require('fs');
// Read the contents of the directory /usr/local/bin asynchronously.
// The callback will be invoked once the operation has either completed
// or failed.
fs.readdir('/usr/local/bin', (err, files) => {
// On error, show it and return
if(err) return console.error(err);
// files is an array containing the names of all entries
// in the directory, excluding '.' (the directory itself)
// and '..' (the parent directory).
// Display directory entries
console.log(files.join(' '));
});
Una variante sincrona è disponibile come readdirSync
che blocca il thread principale e quindi impedisce l'esecuzione di codice asincrono allo stesso tempo. La maggior parte degli sviluppatori evita le funzioni di I / O sincrone per migliorare le prestazioni.
let files;
try {
files = fs.readdirSync('/var/tmp');
} catch(err) {
// An error occurred
console.error(err);
}
Utilizzando un generatore
const fs = require('fs');
// Iterate through all items obtained via
// 'yield' statements
// A callback is passed to the generator function because it is required by
// the 'readdir' method
function run(gen) {
var iter = gen((err, data) => {
if (err) { iter.throw(err); }
return iter.next(data);
});
iter.next();
}
const dirPath = '/usr/local/bin';
// Execute the generator function
run(function* (resume) {
// Emit the list of files in the directory from the generator
var contents = yield fs.readdir(dirPath, resume);
console.log(contents);
});
Lettura da un file in modo sincrono
Per qualsiasi operazione sui file, è necessario il modulo filesystem:
const fs = require('fs');
Leggere una stringa
fs.readFileSync
comporta in modo simile a fs.readFile
, ma non fs.readFile
una richiamata poiché completa in modo sincrono e quindi blocca il thread principale. La maggior parte degli sviluppatori di node.js preferiscono le varianti asincrone che non causeranno praticamente alcun ritardo nell'esecuzione del programma.
Se viene specificata un'opzione di encoding
, verrà restituita una stringa, altrimenti verrà restituito un Buffer
.
// Read a string from another file synchronously
let content;
try {
content = fs.readFileSync('sync.txt', { encoding: 'utf8' });
} catch(err) {
// An error occurred
console.error(err);
}
Eliminazione di un file utilizzando lo scollegamento o lo scollegamento sincronizzato
Elimina un file in modo asincrono:
var fs = require('fs');
fs.unlink('/path/to/file.txt', function(err) {
if (err) throw err;
console.log('file deleted');
});
Puoi anche eliminarlo in modo sincrono *:
var fs = require('fs');
fs.unlinkSync('/path/to/file.txt');
console.log('file deleted');
* evitare i metodi sincroni perché bloccano l'intero processo fino al termine dell'esecuzione.
Lettura di un file in un buffer utilizzando i flussi
Mentre leggendo il contenuto da un file è già asincrono usando il metodo fs.readFile()
, a volte vogliamo ottenere i dati in un flusso rispetto a un semplice callback. Questo ci consente di convogliare questi dati in altre posizioni o di elaborarli al loro interno rispetto a tutti in una volta alla fine.
const fs = require('fs');
// Store file data chunks in this array
let chunks = [];
// We can use this variable to store the final data
let fileBuffer;
// Read file into stream.Readable
let fileStream = fs.createReadStream('text.txt');
// An error occurred with the stream
fileStream.once('error', (err) => {
// Be sure to handle this properly!
console.error(err);
});
// File is done being read
fileStream.once('end', () => {
// create the final data Buffer from data chunks;
fileBuffer = Buffer.concat(chunks);
// Of course, you can do anything else you need to here, like emit an event!
});
// Data is flushed from fileStream in chunks,
// this callback will be executed for each chunk
fileStream.on('data', (chunk) => {
chunks.push(chunk); // push data chunk to array
// We can perform actions on the partial data we have so far!
});
Verifica le autorizzazioni di un file o di una directory
fs.access()
determina se esiste un percorso e quali autorizzazioni ha un utente per il file o la directory in quel percorso. fs.access
non restituisce un risultato piuttosto, se non restituisce un errore, il percorso esiste e l'utente ha le autorizzazioni desiderate.
Le modalità di autorizzazione sono disponibili come proprietà sull'oggetto fs
, fs.constants
-
fs.constants.F_OK
- Hafs.constants.F_OK
lettura / scrittura / esecuzione (se non viene fornita alcuna modalità, questa è l'impostazione predefinita) -
fs.constants.R_OK
- Ha permessi di lettura -
fs.constants.W_OK
- Ha permessi di scrittura -
fs.constants.X_OK
- Ha permessi di esecuzione (Funziona comefs.constants.F_OK
su Windows)
in modo asincrono
var fs = require('fs');
var path = '/path/to/check';
// checks execute permission
fs.access(path, fs.constants.X_OK, (err) => {
if (err) {
console.log("%s doesn't exist", path);
} else {
console.log('can execute %s', path);
}
});
// Check if we have read/write permissions
// When specifying multiple permission modes
// each mode is separated by a pipe : `|`
fs.access(path, fs.constants.R_OK | fs.constants.W_OK, (err) => {
if (err) {
console.log("%s doesn't exist", path);
} else {
console.log('can read/write %s', path);
}
});
sincrono
fs.access
ha anche una versione sincrona fs.accessSync
. Quando si utilizza fs.accessSync
è necessario racchiuderlo all'interno di un blocco try / catch.
// Check write permission
try {
fs.accessSync(path, fs.constants.W_OK);
console.log('can write %s', path);
}
catch (err) {
console.log("%s doesn't exist", path);
}
Evitare le condizioni di gara durante la creazione o l'utilizzo di una directory esistente
A causa della natura asincrona del nodo, creando o utilizzando una directory prima:
- controllando la sua esistenza con
fs.stat()
, quindi - creandolo o usandolo in base ai risultati del controllo di esistenza,
può portare a una condizione di competizione se la cartella viene creata tra il momento del controllo e l'ora della creazione. Il metodo riportato di seguito fs.mkdir()
e fs.mkdirSync()
in wrapper che catturano gli errori che consentono il passaggio dell'eccezione se il codice è EEXIST
(già esistente). Se l'errore è qualcos'altro, come EPERM
(pemission negato), lancia o passa un errore come fanno le funzioni native.
Versione asincrona con fs.mkdir()
var fs = require('fs'); function mkdir (dirPath, callback) { fs.mkdir(dirPath, (err) => { callback(err && err.code !== 'EEXIST' ? err : null); }); } mkdir('./existingDir', (err) => { if (err) return console.error(err.code); // Do something with `./existingDir` here });
Versione sincrona con fs.mkdirSync()
function mkdirSync (dirPath) { try { fs.mkdirSync(dirPath); } catch(e) { if ( e.code !== 'EEXIST' ) throw e; } } mkdirSync('./existing-dir'); // Do something with `./existing-dir` now
Verifica se esiste un file o una directory
in modo asincrono
var fs = require('fs');
fs.stat('path/to/file', function(err) {
if (!err) {
console.log('file or directory exists');
}
else if (err.code === 'ENOENT') {
console.log('file or directory does not exist');
}
});
sincrono
qui, dobbiamo racchiudere la chiamata di funzione in un blocco try/catch
per gestire l'errore.
var fs = require('fs');
try {
fs.statSync('path/to/file');
console.log('file or directory exists');
}
catch (err) {
if (err.code === 'ENOENT') {
console.log('file or directory does not exist');
}
}
Clonazione di un file utilizzando i flussi
Questo programma illustra come è possibile copiare un file utilizzando flussi leggibili e scrivibili utilizzando le createReadStream()
e createWriteStream()
fornite dal modulo del file system.
//Require the file System module
var fs = require('fs');
/*
Create readable stream to file in current directory (__dirname) named 'node.txt'
Use utf8 encoding
Read the data in 16-kilobyte chunks
*/
var readable = fs.createReadStream(__dirname + '/node.txt', { encoding: 'utf8', highWaterMark: 16 * 1024 });
// create writable stream
var writable = fs.createWriteStream(__dirname + '/nodeCopy.txt');
// Write each chunk of data to the writable stream
readable.on('data', function(chunk) {
writable.write(chunk);
});
Copia di file tramite streaming di piping
Questo programma copia un file utilizzando un flusso leggibile e scrivibile con la funzione pipe()
fornita dalla classe stream
// require the file system module
var fs = require('fs');
/*
Create readable stream to file in current directory named 'node.txt'
Use utf8 encoding
Read the data in 16-kilobyte chunks
*/
var readable = fs.createReadStream(__dirname + '/node.txt', { encoding: 'utf8', highWaterMark: 16 * 1024 });
// create writable stream
var writable = fs.createWriteStream(__dirname + '/nodePipe.txt');
// use pipe to copy readable to writable
readable.pipe(writable);
Modifica del contenuto di un file di testo
Esempio. Sostituirà la parola email
con un name
in un file di testo index.txt
con la semplice replace(/email/gim, 'name')
RegExp replace(/email/gim, 'name')
var fs = require('fs');
fs.readFile('index.txt', 'utf-8', function(err, data) {
if (err) throw err;
var newValue = data.replace(/email/gim, 'name');
fs.writeFile('index.txt', newValue, 'utf-8', function(err, data) {
if (err) throw err;
console.log('Done!');
})
})
Determinazione del numero di righe di un file di testo
app.js
const readline = require('readline');
const fs = require('fs');
var file = 'path.to.file';
var linesCount = 0;
var rl = readline.createInterface({
input: fs.createReadStream(file),
output: process.stdout,
terminal: false
});
rl.on('line', function (line) {
linesCount++; // on each linebreak, add +1 to 'linesCount'
});
rl.on('close', function () {
console.log(linesCount); // print the result when the 'close' event is called
});
Uso:
nodo app
Leggere un file riga per riga
app.js
const readline = require('readline');
const fs = require('fs');
var file = 'path.to.file';
var rl = readline.createInterface({
input: fs.createReadStream(file),
output: process.stdout,
terminal: false
});
rl.on('line', function (line) {
console.log(line) // print the content of the line on each linebreak
});
Uso:
nodo app