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);
}

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

  1. sprawdzanie jego istnienia za pomocą fs.stat()
  2. 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



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow