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:
promise
, che rende più facile l’uso in un progetto più ampio. 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