Node.js
Filsystem I / O
Sök…
Anmärkningar
I Node.js utförs resursintensiva operationer som I / O asynkront men har en synkron motsvarighet (t.ex. finns det en fs.readFile
och dess motsvarighet är fs.readFileSync
). Eftersom Node är enkeltrådad, bör du vara försiktig när du använder synkrona operationer, eftersom de blockerar hela processen.
Om en process blockeras av en synkron operation stoppas hela exekveringscykeln (inklusive händelsslingan). Det betyder att annan asynkron kod, inklusive händelser och händelseshanterare, inte kommer att köras och ditt program kommer att fortsätta att vänta tills den enda blockeringsoperationen har slutförts.
Det finns lämpliga användningar för både synkrona och asynkrona operationer, men man måste se till att de används korrekt.
Skriva till en fil med writeFile eller 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
fungerar på samma sätt som fs.writeFile
, men tar inte ett återuppringning eftersom det slutförs synkront och därför blockerar huvudtråden. De flesta utvecklare av node.js föredrar de asynkrona varianterna som nästan inte kommer att försena programutförandet.
Obs! Att blockera huvudtråden är dålig praxis i node.js. Synkronfunktion ska endast användas vid felsökning eller när inga andra alternativ är tillgängliga.
// 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);
}
Asynkront läs från filer
Använd filsystemmodulen för alla filåtgärder:
const fs = require('fs');
Med kodning
I det här exemplet, läs hello.txt
från katalogen /tmp
. Denna åtgärd kommer att slutföras i bakgrunden och återuppringningen sker vid slutförande eller misslyckande:
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);
});
Utan kodning
Läs den binära filen binary.txt
från den aktuella katalogen, asynkront i bakgrunden. Observera att vi inte ställer in alternativet 'kodning' - detta förhindrar Node.js från att avkoda innehållet till en sträng:
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'));
});
Relativa vägar
Kom ihåg att ditt skript i allmänhet kan köras med en godtycklig aktuell arbetskatalog. För att adressera en fil i förhållande till det aktuella skriptet använder du __dirname
eller __filename
:
fs.readFile(path.resolve(__dirname, 'someFile'), (err, binaryContent) => {
//Rest of Function
}
Lista kataloginnehåll med readdir eller 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(' '));
});
En synkron variant finns som readdirSync
som blockerar readdirSync
och därför förhindrar körning av asynkron kod samtidigt. De flesta utvecklare undviker synkrona IO-funktioner för att förbättra prestandan.
let files;
try {
files = fs.readdirSync('/var/tmp');
} catch(err) {
// An error occurred
console.error(err);
}
Med hjälp av en 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);
});
Läser från en fil synkront
För alla filoperationer behöver du filsystemmodulen:
const fs = require('fs');
Läsa en sträng
fs.readFileSync
beter sig på samma sätt som fs.readFile
, men tar inte ett återuppringning eftersom det slutförs synkront och därför blockerar huvudtråden. De flesta utvecklare av node.js föredrar de asynkrona varianterna som nästan inte kommer att försena programutförandet.
Om ett encoding
anges returneras en sträng, annars returneras en 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);
}
Radera en fil med unlink eller unlinkSync
Radera en fil asynkront:
var fs = require('fs');
fs.unlink('/path/to/file.txt', function(err) {
if (err) throw err;
console.log('file deleted');
});
Du kan också ta bort det synkront *:
var fs = require('fs');
fs.unlinkSync('/path/to/file.txt');
console.log('file deleted');
* Undvik synkrona metoder eftersom de blockerar hela processen tills körningen är klar.
Läsa en fil i en buffert med strömmar
Medan läsning av innehåll från en fil redan är asynkron med fs.readFile()
-metoden, vill vi ibland få fs.readFile()
i en Stream kontra i en enkel återuppringning. Detta gör att vi kan leda denna information till andra platser eller bearbeta dem när de kommer i motsats samtidigt i slutet.
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!
});
Kontrollera behörigheter för en fil eller katalog
fs.access()
avgör om en sökväg finns och vilka behörigheter en användare har till filen eller katalogen på den sökvägen. fs.access
inte ett resultat snarare, om det inte returnerar ett fel finns sökvägen och användaren har önskade behörigheter.
Tillståndslägen är tillgängliga som en egenskap på fs
objektet, fs.constants
-
fs.constants.F_OK
- Har läs / skriv / kör körningar (Om inget läge tillhandahålls är detta standard) -
fs.constants.R_OK
- Harfs.constants.R_OK
-
fs.constants.W_OK
- Harfs.constants.W_OK
-
fs.constants.X_OK
- Har körningar (fungerar på samma sätt somfs.constants.F_OK
på Windows)
asynkront
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);
}
});
synkront
fs.access
har också en synkron version fs.accessSync
. När du använder fs.accessSync
måste du bifoga det i ett try / catch-block.
// 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);
}
Undvika tävlingsvillkor när du skapar eller använder en befintlig katalog
På grund av Nodes asynkrona natur skapar eller använder du en katalog först:
- kontrollera om det finns med
fs.stat()
, då - skapa eller använda den beroende på resultaten av existenskontrollen,
kan leda till ett tävlingsvillkor om mappen skapas mellan tidpunkten för kontrollen och skapelsestiden. Metoden nedan fs.mkdir()
och fs.mkdirSync()
i felupptagande omslag som låter undantaget passera om dess kod är EEXIST
(finns redan). Om felet är något annat, som EPERM
(pemission nekad), kasta eller skicka ett fel som de ursprungliga funktionerna gör.
Asynkron version med 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 });
Synkron version med 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
Kontrollera om en fil eller en katalog finns
asynkront
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');
}
});
synkront
här måste vi pakka in funktionssamtalet i ett try/catch
block för att hantera fel.
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');
}
}
Kloning av en fil med strömmar
Detta program illustrerar hur man kan kopiera en fil med läsbara och skrivbara strömmar med createReadStream()
och createWriteStream()
tillhandahålls av filsystemmodulen.
//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);
});
Kopiera filer genom pipingströmmar
Detta program kopierar en fil med hjälp av läsbar och en skrivbar ström med funktionen pipe()
tillhandahålls av strömklassen
// 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);
Ändra innehållet i en textfil
Exempel. Det kommer att ersätta ordet email
till ett name
i en textfil index.txt
med enkel 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!');
})
})
Bestämning av räkneantalet för en textfil
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
});
Användande:
nod app
Läsa en fil rad för rad
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
});
Användande:
nod app