Il modo più veloce per copiare il file in node.js

Il progetto a cui sto lavorando (node.js) implica molte operazioni con il file system (copia / lettura / scrittura ecc.). Mi piacerebbe sapere quali sono i metodi più veloci e sarei felice di avere qualche consiglio.

Questo è un buon modo per copiare un file in una riga di codice usando gli stream:

var fs = require('fs'); fs.createReadStream('test.log').pipe(fs.createWriteStream('newLog.log')); 

Stesso meccanismo, ma questo aggiunge la gestione degli errori:

 function copyFile(source, target, cb) { var cbCalled = false; var rd = fs.createReadStream(source); rd.on("error", function(err) { done(err); }); var wr = fs.createWriteStream(target); wr.on("error", function(err) { done(err); }); wr.on("close", function(ex) { done(); }); rd.pipe(wr); function done(err) { if (!cbCalled) { cb(err); cbCalled = true; } } } 

Non ero in grado di far funzionare il metodo createReadStream/createWriteStream per qualche motivo, ma usando il modulo fs-extra npm funzionava subito. Non sono sicuro della differenza di prestazioni però.

FS-in più

npm install --save fs-extra

 var fs = require('fs-extra'); fs.copySync(path.resolve(__dirname,'./init/xxx.json'), 'xxx.json'); 

Veloce da scrivere e comodo da usare, con promise e gestione degli errori.

 function copyFile(source, target) { var rd = fs.createReadStream(source); var wr = fs.createWriteStream(target); return new Promise(function(resolve, reject) { rd.on('error', reject); wr.on('error', reject); wr.on('finish', resolve); rd.pipe(wr); }).catch(function(error) { rd.destroy(); wr.end(); throw error; }); } 

Lo stesso con syntax asincrona / attendi:

 async function copyFile(source, target) { var rd = fs.createReadStream(source); var wr = fs.createWriteStream(target); try { return await new Promise(function(resolve, reject) { rd.on('error', reject); wr.on('error', reject); wr.on('finish', resolve); rd.pipe(wr); }); } catch (error) { rd.destroy(); wr.end(); throw error; } } 

Dal momento che Node.js 8.5.0 abbiamo nuovi metodi fs.copyFile e fs.copyFileSync .

Esempio di utilizzo:

 var fs = require('fs'); // destination.txt will be created or overwritten by default. fs.copyFile('source.txt', 'destination.txt', (err) => { if (err) throw err; console.log('source.txt was copied to destination.txt'); }); 

Bene, di solito è bene evitare operazioni di file asincrone. Ecco l’esempio di sincronizzazione breve (ovvero senza gestione errori):

 var fs = require('fs'); fs.writeFileSync(targetFile, fs.readFileSync(sourceFile)); 

La soluzione di Mike Schilling con la gestione degli errori con una scorciatoia per il gestore di eventi di errore.

 function copyFile(source, target, cb) { var cbCalled = false; var rd = fs.createReadStream(source); rd.on("error", done); var wr = fs.createWriteStream(target); wr.on("error", done); wr.on("close", function(ex) { done(); }); rd.pipe(wr); function done(err) { if (!cbCalled) { cb(err); cbCalled = true; } } } 

Se non ti interessa che sia asincrono e non copi i file di dimensioni gigabyte, preferiresti non aggiungere un’altra dipendenza solo per una singola funzione:

 function copySync(src, dest) { if (!fs.existsSync(src)) { return false; } var data = fs.readFileSync(src, 'utf-8'); fs.writeFileSync(dest, data); } 

La soluzione di benweet controlla la visibilità del file prima della copia:

 function copy(from, to) { return new Promise(function (resolve, reject) { fs.access(from, fs.F_OK, function (error) { if (error) { reject(error); } else { var inputStream = fs.createReadStream(from); var outputStream = fs.createWriteStream(to); function rejectCleanup(error) { inputStream.destroy(); outputStream.end(); reject(error); } inputStream.on('error', rejectCleanup); outputStream.on('error', rejectCleanup); outputStream.on('finish', resolve); inputStream.pipe(outputStream); } }); }); } 

La soluzione di Mike , ma con le promesse:

 const FileSystem = require('fs'); exports.copyFile = function copyFile(source, target) { return new Promise((resolve,reject) => { const rd = FileSystem.createReadStream(source); rd.on('error', err => reject(err)); const wr = FileSystem.createWriteStream(target); wr.on('error', err => reject(err)); wr.on('close', () => resolve()); rd.pipe(wr); }); }; 

Miglioramento di un’altra risposta.

Caratteristiche:

  • Se le cartelle dst non esistono, la creerà automaticamente. L’altra risposta genererà solo errori.
  • Restituisce una promise , che rende più facile l’uso in un progetto più ampio.
  • Ti permette di copiare più file e la promise sarà fatta quando tutti saranno copiati.

Uso:

 var onePromise = copyFilePromise("src.txt", "dst.txt"); var anotherPromise = copyMultiFilePromise(new Array(new Array("src1.txt", "dst1.txt"), new Array("src2.txt", "dst2.txt"))); 

Codice:

 function copyFile(source, target, cb) { console.log("CopyFile", source, target); var ensureDirectoryExistence = function (filePath) { var dirname = path.dirname(filePath); if (fs.existsSync(dirname)) { return true; } ensureDirectoryExistence(dirname); fs.mkdirSync(dirname); } ensureDirectoryExistence(target); var cbCalled = false; var rd = fs.createReadStream(source); rd.on("error", function (err) { done(err); }); var wr = fs.createWriteStream(target); wr.on("error", function (err) { done(err); }); wr.on("close", function (ex) { done(); }); rd.pipe(wr); function done(err) { if (!cbCalled) { cb(err); cbCalled = true; } } } function copyFilePromise(source, target) { return new Promise(function (accept, reject) { copyFile(source, target, function (data) { if (data === undefined) { accept(); } else { reject(data); } }); }); } function copyMultiFilePromise(srcTgtPairArr) { var copyFilePromiseArr = new Array(); srcTgtPairArr.forEach(function (srcTgtPair) { copyFilePromiseArr.push(copyFilePromise(srcTgtPair[0], srcTgtPair[1])); }); return Promise.all(copyFilePromiseArr); } 

tutte le soluzioni di cui sopra che non verificano l’esistenza di un file sorgente sono pericolose … ad es

 fs.stat(source, function(err,stat) { if (err) { reject(err) } 

altrimenti c’è un rischio in uno scenario nel caso in cui la fonte e il target siano stati sostituiti da un errore, i dati saranno persi in modo permanente senza notare alcun errore.

Perché non utilizzare nodejs integrato nella funzione di copia?

Fornisce sia la versione asincrona che la sincronizzazione:

 const fs = require('fs'); // destination.txt will be created or overwritten by default. fs.copyFile('source.txt', 'destination.txt', (err) => { if (err) throw err; console.log('source.txt was copied to destination.txt'); }); 

https://nodejs.org/api/fs.html#fs_fs_copyfilesync_src_dest_flags