Das Projekt, an dem ich arbeite (node.js), impliziert viele Operationen mit dem Dateisystem (Kopieren / Lesen / Schreiben usw.). Ich würde gerne wissen, welche Methoden am schnellsten sind, und würde mich über einen Rat freuen. Vielen Dank.
Das Projekt, an dem ich arbeite (node.js), impliziert viele Operationen mit dem Dateisystem (Kopieren / Lesen / Schreiben usw.). Ich würde gerne wissen, welche Methoden am schnellsten sind, und würde mich über einen Rat freuen. Vielen Dank.
Antworten:
Dies ist eine gute Möglichkeit, eine Datei mithilfe von Streams in eine Codezeile zu kopieren:
var fs = require('fs');
fs.createReadStream('test.log').pipe(fs.createWriteStream('newLog.log'));
In Knoten v8.5.0 wurde copyFile hinzugefügt
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');
});
createReadStream
als auch createWriteStream
auf Fehler überprüfen möchten , damit Sie keinen Einzeiler erhalten (obwohl dies immer noch genauso schnell ist).
cp test.log newLog.log
Via require('child_process').exec
?
copy
ist im Gegensatz zu einer vollständigen Node.js-Lösung unter Windows nicht portierbar.
child_process.execFile('/bin/cp', ['--no-target-directory', source, target])
.
fs.createReadStream('./init/xxx.json').pipe(fs.createWriteStream('xxx.json'));
Gleicher Mechanismus, aber dies fügt eine Fehlerbehandlung hinzu:
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;
}
}
}
WriteStream
Testament wird es nur entpfeifen. Sie müssten sich rd.destroy()
selbst anrufen . Zumindest ist mir das passiert. Leider gibt es außer dem Quellcode nicht viel Dokumentation.
cb
? Was sollen wir als drittes Argument eingeben?
Ich konnte die createReadStream/createWriteStream
Methode aus irgendeinem Grund nicht zum fs-extra
Laufen bringen , aber mit dem npm-Modul funktionierte es sofort. Ich bin mir jedoch nicht sicher über den Leistungsunterschied.
npm install --save fs-extra
var fs = require('fs-extra');
fs.copySync(path.resolve(__dirname,'./init/xxx.json'), 'xxx.json');
fs.copy(src, dst, callback);
diese sollten das Problem von @ mvillar lösen.
Seit Node.js 8.5.0 haben wir neue Methoden fs.copyFile und fs.copyFileSync .
Anwendungsbeispiel:
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');
});
copyFile()
beim Überschreiben längerer Dateien Fehler auftreten. Mit freundlicher Genehmigung von uv_fs_copyfile()
till Node v8.7.0 (libuv 1.15.0). siehe github.com/libuv/libuv/pull/1552
Schnell zu schreiben und bequem zu bedienen, mit Versprechen und Fehlermanagement.
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;
});
}
Gleiches gilt für die asynchrone / warten-Syntax:
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;
}
}
new Promise(function(resolve, reject) { resolve(1); resolve(2); reject(3); reject(4); console.log("DONE"); }).then(console.log.bind(console), function(e){console.log("E", e);});
die Spezifikation dazu getestet und nachgeschlagen, und Sie haben Recht: Der Versuch, ein gelöstes Versprechen zu lösen oder abzulehnen, hat keine Auswirkung. Vielleicht könnten Sie Ihre Antwort erweitern und erklären, warum Sie die Funktion auf diese Weise geschrieben haben? Danke :-)
close
sollte finish
für beschreibbare Streams.
/dev/stdin
wird, ist dies ein Fehler. Github.com/joyent/node/issues/25375
Normalerweise ist es gut, asynchrone Dateivorgänge zu vermeiden. Hier ist das kurze Synchronisierungsbeispiel (dh keine Fehlerbehandlung):
var fs = require('fs');
fs.writeFileSync(targetFile, fs.readFileSync(sourceFile));
*Sync
Methoden sind völlig gegen die Philosophie von nodejs! Ich denke auch, dass sie langsam veraltet sind. Die ganze Idee von nodejs ist, dass es Single-Threaded und ereignisgesteuert ist.
Mike Schillings Lösung mit Fehlerbehandlung mit einer Verknüpfung für den Fehlerereignishandler.
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;
}
}
}
Wenn Sie sich nicht darum kümmern, dass es asynchron ist, und keine Dateien in Gigabyte-Größe kopieren und lieber keine weitere Abhängigkeit nur für eine einzelne Funktion hinzufügen möchten:
function copySync(src, dest) {
var data = fs.readFileSync(src);
fs.writeFileSync(dest, data);
}
fs.existsSync
Anruf sollte weggelassen werden. Die Datei könnte in der Zeit zwischen dem fs.existsSync
Anruf und dem fs.readFileSync
Anruf verschwinden , was bedeutet, dass der fs.existsSync
Anruf uns vor nichts schützt.
false
bei fs.existsSync
Fehlschlägen wahrscheinlich eine schlechte Ergonomie, da nur wenige Verbraucher copySync
daran denken, den Rückgabewert bei jedem Aufruf manuell zu überprüfen, genauso wenig wie bei fs.writeFileSync
et al. . Das Auslösen einer Ausnahme ist eigentlich vorzuziehen.
const fs = require("fs");
fs.copyFileSync("filepath1", "filepath2"); //fs.copyFileSync("file1.txt", "file2.txt");
Dies ist, was ich persönlich benutze, um eine Datei zu kopieren und eine andere Datei mit node.js zu ersetzen :)
Für schnelle Kopien sollten Sie die fs.constants.COPYFILE_FICLONE
Flagge verwenden. Es ermöglicht (für Dateisysteme, die dies unterstützen), den Inhalt der Datei nicht tatsächlich zu kopieren. Es wird nur ein neuer Dateieintrag erstellt, der jedoch auf einen Copy-on-Write- "Klon" der Quelldatei verweist .
Nichts / weniger zu tun ist der schnellste Weg, etwas zu tun;)
https://nodejs.org/api/fs.html#fs_fs_copyfile_src_dest_flags_callback
let fs = require("fs");
fs.copyFile(
"source.txt",
"destination.txt",
fs.constants.COPYFILE_FICLONE,
(err) => {
if (err) {
// TODO: handle error
console.log("error");
}
console.log("success");
}
);
Verwenden Sie stattdessen Versprechen:
let fs = require("fs");
let util = require("util");
let copyFile = util.promisify(fs.copyFile);
copyFile(
"source.txt",
"destination.txt",
fs.constants.COPYFILE_FICLONE
)
.catch(() => console.log("error"))
.then(() => console.log("success"));
fs.promises.copyFile
Die Lösung von benweet überprüft die Sichtbarkeit der Datei vor dem Kopieren:
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);
}
});
});
}
Warum nicht NodeJs verwenden, die in die Kopierfunktion integriert sind?
Es bietet sowohl eine asynchrone als auch eine synchronisierte Version:
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
Mikes Lösung , aber mit Versprechungen:
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);
});
};
Verbesserung einer anderen Antwort.
Eigenschaften:
promise
, was die Verwendung in einem größeren Projekt erleichtert.Verwendungszweck:
var onePromise = copyFilePromise("src.txt", "dst.txt");
var anotherPromise = copyMultiFilePromise(new Array(new Array("src1.txt", "dst1.txt"), new Array("src2.txt", "dst2.txt")));
Code:
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);
}
Alle oben genannten Lösungen, die das Vorhandensein einer Quelldatei nicht überprüfen, sind gefährlich ... z
fs.stat(source, function(err,stat) { if (err) { reject(err) }
Andernfalls besteht in einem Szenario das Risiko, dass Ihre Daten dauerhaft verloren gehen, ohne dass ein Fehler bemerkt wird, wenn Quelle und Ziel versehentlich ersetzt werden.