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 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 als fs.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:

  1. controleren op zijn bestaan met fs.stat() en vervolgens
  2. 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



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow