Node.js
System plików I / O
Szukaj…
Uwagi
W Node.js operacje wymagające dużych zasobów, takie jak operacje we / wy, są wykonywane asynchronicznie , ale mają synchroniczny odpowiednik (np. Istnieje plik fs.readFile
a jego odpowiednikiem jest fs.readFileSync
). Ponieważ Węzeł jest jednowątkowy, należy zachować ostrożność podczas korzystania z operacji synchronicznych , ponieważ będą one blokować cały proces.
Jeśli proces zostanie zablokowany przez operację synchroniczną, cały cykl wykonania (w tym pętla zdarzeń) zostanie zatrzymany. Oznacza to, że inny kod asynchroniczny, w tym zdarzenia i procedury obsługi zdarzeń, nie będzie działał, a program będzie nadal czekał na zakończenie operacji pojedynczego blokowania.
Istnieją odpowiednie zastosowania zarówno dla operacji synchronicznych, jak i asynchronicznych, ale należy zachować ostrożność, aby były one właściwie wykorzystywane.
Zapis do pliku za pomocą writeFile lub 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
zachowuje się podobnie do fs.writeFile
, ale nie fs.writeFile
wywołania zwrotnego, ponieważ wykonuje się synchronicznie, a zatem blokuje główny wątek. Większość programistów node.js woli warianty asynchroniczne, które praktycznie nie powodują opóźnienia w wykonywaniu programu.
Uwaga: Blokowanie głównego wątku jest złą praktyką w node.js. Z funkcji synchronicznej należy korzystać tylko podczas debugowania lub gdy żadne inne opcje nie są dostępne.
// 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);
}
Asynchronicznie odczytywane z plików
Użyj modułu systemu plików do wszystkich operacji na plikach:
const fs = require('fs');
Z kodowaniem
W tym przykładzie przeczytaj hello.txt
z katalogu /tmp
. Ta operacja zostanie zakończona w tle, a wywołanie zwrotne nastąpi po zakończeniu lub niepowodzeniu:
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);
});
Bez kodowania
Odczytaj plik binarny binary.txt
z bieżącego katalogu, asynchronicznie w tle. Pamiętaj, że nie ustawiamy opcji „kodowania” - zapobiega to dekodowaniu zawartości Node.js do łańcucha:
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'));
});
Ścieżki względne
Należy pamiętać, że w ogólnym przypadku skrypt może być uruchamiany z dowolnym bieżącym katalogiem roboczym. Aby zaadresować plik względem bieżącego skryptu, użyj __dirname
lub __filename
:
fs.readFile(path.resolve(__dirname, 'someFile'), (err, binaryContent) => {
//Rest of Function
}
Wyświetlanie zawartości katalogu za pomocą readdir lub 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(' '));
});
Wariant synchroniczny jest dostępny jako readdirSync
który blokuje główny wątek, a tym samym uniemożliwia wykonanie kodu asynchronicznego w tym samym czasie. Większość programistów unika synchronicznych funkcji IO w celu poprawy wydajności.
let files;
try {
files = fs.readdirSync('/var/tmp');
} catch(err) {
// An error occurred
console.error(err);
}
Korzystanie z generatora
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);
});
Odczytywanie z pliku synchronicznie
Do wszelkich operacji na plikach potrzebny będzie moduł systemu plików:
const fs = require('fs');
Czytanie łańcucha
fs.readFileSync
zachowuje się podobnie do fs.readFile
, ale nie fs.readFile
wywołania zwrotnego, ponieważ wykonuje się synchronicznie, a zatem blokuje główny wątek. Większość programistów node.js woli warianty asynchroniczne, które praktycznie nie powodują opóźnienia w wykonywaniu programu.
Jeśli podano opcję encoding
, łańcuch zostanie zwrócony, w przeciwnym razie zostanie zwrócony 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);
}
Usuwanie pliku za pomocą unlink lub unlinkSync
Usuń plik asynchronicznie:
var fs = require('fs');
fs.unlink('/path/to/file.txt', function(err) {
if (err) throw err;
console.log('file deleted');
});
Możesz również usunąć go synchronicznie *:
var fs = require('fs');
fs.unlinkSync('/path/to/file.txt');
console.log('file deleted');
* unikaj metod synchronicznych, ponieważ blokują cały proces do czasu zakończenia wykonywania.
Odczytywanie pliku do bufora za pomocą strumieni
Podczas gdy czytanie zawartości pliku jest już asynchroniczne przy użyciu metody fs.readFile()
, czasami chcemy uzyskać dane w strumieniu w porównaniu z prostym wywołaniem zwrotnym. To pozwala nam przesyłać te dane do innych lokalizacji lub przetwarzać je na bieżąco w porównaniu do wszystkich naraz.
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!
});
Sprawdź uprawnienia do pliku lub katalogu
fs.access()
określa, czy istnieje ścieżka i jakie uprawnienia ma użytkownik do pliku lub katalogu w tej ścieżce. fs.access
raczej nie zwraca wyniku, jeśli nie zwraca błędu, ścieżka istnieje, a użytkownik ma wymagane uprawnienia.
Tryby uprawnień są dostępne jako właściwość obiektu fs
, fs.constants
-
fs.constants.F_OK
- Ma uprawnienia do odczytu / zapisu / wykonania (jeśli nie podano żadnego trybu, jest to ustawienie domyślne) -
fs.constants.R_OK
- Ma uprawnienia do odczytu -
fs.constants.W_OK
- Ma uprawnienia do zapisu -
fs.constants.X_OK
- Ma uprawnienia do wykonywania (działa tak samo jakfs.constants.F_OK
w systemie Windows)
Asynchronicznie
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);
}
});
Synchronicznie
fs.access
ma również wersję synchroniczną fs.accessSync
. Korzystając z fs.accessSync
musisz fs.accessSync
go w bloku 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);
}
Unikanie warunków wyścigu podczas tworzenia lub korzystania z istniejącego katalogu
Ze względu na asynchroniczny charakter węzła najpierw należy utworzyć lub użyć katalogu:
- sprawdzanie jego istnienia za pomocą
fs.stat()
- tworzenie lub używanie go w zależności od wyników kontroli istnienia,
może prowadzić do wyścigu, jeśli folder zostanie utworzony między czasem sprawdzania a czasem utworzenia. Poniższa metoda otacza fs.mkdir()
i fs.mkdirSync()
w przechwytujących błędy opakowaniach, które przepuszczają wyjątek, jeśli jego kod to EEXIST
(już istnieje). Jeśli błąd dotyczy czegoś innego, na przykład EPERM
(odmowa pemisji), wyrzuć lub przekaż błąd, tak jak robią to funkcje natywne.
Wersja asynchroniczna z 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 });
Wersja synchroniczna z 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
Sprawdzanie, czy plik lub katalog istnieje
Asynchronicznie
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');
}
});
Synchronicznie
tutaj musimy zawinąć wywołanie funkcji w blok try/catch
, aby obsłużyć błąd.
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');
}
}
Klonowanie pliku przy użyciu strumieni
Ten program ilustruje sposób kopiowania pliku przy użyciu czytelnych i zapisywalnych strumieni za pomocą funkcji createReadStream()
i createWriteStream()
zapewnianych przez moduł systemu plików.
//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);
});
Kopiowanie plików przez przesyłanie strumieniowe strumieni
Ten program kopiuje plik przy użyciu czytelnego i zapisywalnego strumienia za pomocą funkcji pipe()
zapewnianej przez klasę 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);
Zmiana zawartości pliku tekstowego
Przykład. Będzie zastępować słowo email
do name
w pliku tekstowym index.txt
prostym 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!');
})
})
Określanie liczby wierszy pliku tekstowego
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
});
Stosowanie:
aplikacja węzła
Czytanie pliku linia po linii
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
});
Stosowanie:
aplikacja węzła