Node.js
Bestandssysteem I / O
Zoeken…
Opmerkingen
In Node.js worden resource-intensieve bewerkingen zoals I / O asynchroon uitgevoerd, maar hebben een synchrone tegenhanger (er bestaat bijvoorbeeld een fs.readFile
en de tegenhanger is fs.readFileSync
). Omdat Node single-threaded is, moet u voorzichtig zijn bij het gebruik van synchrone bewerkingen, omdat deze het hele proces blokkeren.
Als een proces wordt geblokkeerd door een synchrone bewerking, wordt de volledige uitvoeringscyclus (inclusief de gebeurtenislus) gestopt. Dat betekent dat andere asynchrone code, inclusief gebeurtenissen en gebeurtenishandlers, niet worden uitgevoerd en dat uw programma blijft wachten tot de blokkering is voltooid.
Er zijn geschikte toepassingen voor zowel synchrone als asynchrone bewerkingen, maar er moet op worden gelet dat ze correct worden gebruikt.
Schrijven naar een bestand met writeFile of 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
gedraagt zich op dezelfde manier als fs.writeFile
, maar neemt geen callback aan omdat het synchroon wordt voltooid en daarom de fs.writeFile
blokkeert. De meeste ontwikkelaars van node.js geven de voorkeur aan de asynchrone varianten die vrijwel geen vertraging in de uitvoering van het programma veroorzaken.
Opmerking: het blokkeren van de hoofdthread is een slechte gewoonte in node.js. Synchrone functie mag alleen worden gebruikt bij foutopsporing of wanneer er geen andere opties beschikbaar zijn.
// 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);
}
Asynchroon lezen van bestanden
Gebruik de bestandssysteemmodule voor alle bestandsbewerkingen:
const fs = require('fs');
Met codering
Lees in dit voorbeeld hello.txt
uit de directory /tmp
. Deze bewerking wordt op de achtergrond voltooid en de terugbelactie vindt plaats bij voltooiing of mislukking:
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);
});
Zonder codering
Lees het binaire bestand binary.txt
uit de huidige map, asynchroon op de achtergrond. Merk op dat we de optie 'codering' niet instellen - dit voorkomt dat Node.js de inhoud in een string decodeert:
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'));
});
Relatieve paden
Houd er rekening mee dat uw script in het algemeen kan worden uitgevoerd met een willekeurige huidige werkmap. Gebruik __dirname
of __filename
om een bestand ten opzichte van het huidige script te __filename
:
fs.readFile(path.resolve(__dirname, 'someFile'), (err, binaryContent) => {
//Rest of Function
}
Directory-inhoud weergeven met readdir of 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(' '));
});
Er is een synchrone variant beschikbaar als readdirSync
die de readdirSync
blokkeert en daarom tegelijkertijd de uitvoering van asynchrone code voorkomt. De meeste ontwikkelaars vermijden synchrone IO-functies om de prestaties te verbeteren.
let files;
try {
files = fs.readdirSync('/var/tmp');
} catch(err) {
// An error occurred
console.error(err);
}
Gebruik een generator
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);
});
Synchroon uit een bestand lezen
Voor bestandsbewerkingen hebt u de bestandssysteemmodule nodig:
const fs = require('fs');
Een string lezen
fs.readFileSync
gedraagt zich op dezelfde manier als fs.readFile
, maar neemt geen callback aan omdat het synchroon wordt voltooid en daarom de fs.readFile
blokkeert. De meeste ontwikkelaars van node.js geven de voorkeur aan de asynchrone varianten die vrijwel geen vertraging in de uitvoering van het programma veroorzaken.
Als een encoding
is opgegeven, wordt een tekenreeks geretourneerd, anders wordt een Buffer
geretourneerd.
// 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);
}
Een bestand verwijderen met Unlink of UnlinkSync
Een bestand asynchroon verwijderen:
var fs = require('fs');
fs.unlink('/path/to/file.txt', function(err) {
if (err) throw err;
console.log('file deleted');
});
Je kunt het ook synchroon verwijderen *:
var fs = require('fs');
fs.unlinkSync('/path/to/file.txt');
console.log('file deleted');
* vermijd synchrone methoden omdat ze het hele proces blokkeren totdat de uitvoering is voltooid.
Een bestand in een buffer lezen met behulp van streams
Hoewel het lezen van inhoud uit een bestand al asynchroon is met de methode fs.readFile()
, willen we soms de gegevens in een stream krijgen versus in een eenvoudige callback. Dit stelt ons in staat om deze gegevens naar andere locaties door te sturen of te verwerken zoals ze aan het einde binnenkomen, allemaal tegelijk.
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!
});
Controleer de machtigingen van een bestand of map
fs.access()
bepaalt of er een pad bestaat en welke machtigingen een gebruiker heeft voor het bestand of de map op dat pad. fs.access
retourneert niet eerder een resultaat, als het geen fout retourneert, bestaat het pad en heeft de gebruiker de gewenste machtigingen.
De toestemmingsmodi zijn beschikbaar als een eigenschap van het fs
object, fs.constants
-
fs.constants.F_OK
- Heeft lees- / schrijf- / uitvoermachtigingen (als er geen modus is opgegeven, is dit de standaard) -
fs.constants.R_OK
- Heeft leesrechten -
fs.constants.W_OK
- Heeft schrijfrechten -
fs.constants.X_OK
- Heeft uitvoeringsrechten (werkt hetzelfde alsfs.constants.F_OK
op Windows)
asynchroon
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);
}
});
synchroon
fs.access
ook een synchrone versie fs.accessSync
. Wanneer u fs.accessSync
, moet u het binnen een try / catch-blok plaatsen.
// 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);
}
Raceomstandigheden vermijden bij het maken of gebruiken van een bestaande map
Vanwege de asynchrone aard van Node, moet eerst een map worden gemaakt of gebruikt:
- controleren op zijn bestaan met
fs.stat()
en vervolgens - maken of gebruiken afhankelijk van de resultaten van de aanwezigheidscontrole,
kan leiden tot een race-conditie als de map wordt aangemaakt tussen het tijdstip van de controle en het tijdstip van creatie. De onderstaande methode wraps fs.mkdir()
en fs.mkdirSync()
in fs.mkdirSync()
wrappers die de uitzondering laten passeren als de code EEXIST
(al bestaat). Als de fout iets anders is, zoals EPERM
(pemission geweigerd), gooi of passeer dan een fout zoals de native functies doen.
Asynchrone versie met 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 });
Synchrone versie met 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
Controleren of er een bestand of map bestaat
asynchroon
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');
}
});
synchroon
hier moeten we de functieaanroep in een try/catch
blok wikkelen om fouten af te handelen.
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');
}
}
Een bestand klonen met behulp van streams
Dit programma illustreert hoe men een bestand kan kopiëren met behulp van leesbare en beschrijfbare streams met behulp van de createReadStream()
en createWriteStream()
worden geboden door de bestandssysteemmodule.
//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);
});
Bestanden kopiëren door piping streams
Dit programma kopieert een bestand met behulp van leesbare en een beschrijfbare stream met de functie pipe()
van de streamklasse
// 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);
De inhoud van een tekstbestand wijzigen
Voorbeeld. Het zal het woord email
vervangen door een name
in een tekstbestand index.txt
door eenvoudige 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!');
})
})
Bepalen van het aantal regels van een tekstbestand
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
});
Gebruik:
knooppunt app
Een bestand regel voor regel lezen
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
});
Gebruik:
knooppunt app