Das Projekt, an dem ich arbeite (Node.js), impliziert viele Operationen mit dem Dateisystem (Kopieren, Lesen, Schreiben usw.).
Welche Methoden sind die schnellsten?
Bonbonz
Das Projekt, an dem ich arbeite (Node.js), impliziert viele Operationen mit dem Dateisystem (Kopieren, Lesen, Schreiben usw.).
Welche Methoden sind die schnellsten?
Miguel Sánchez González
Verwenden Sie die integrierte Standardmethode fs.copyFile
:
const fs = require('fs');
// File 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');
});
Wenn Sie alte End-of-Life-Versionen von Node.js unterstützen müssen, gehen Sie wie folgt in Versionen vor, die dies nicht unterstützen fs.copyFile
:
const fs = require('fs');
fs.createReadStream('test.log').pipe(fs.createWriteStream('newLog.log'));
Denken Sie nur daran, dass Sie im wirklichen Leben beide überprüfen möchten createReadStream
und createWriteStream
für Fehler, sodass Sie keinen Einzeiler erhalten würden (obwohl es immer noch genauso schnell wäre).
– Ebohlmann
4. Juli 12 um 0:37 Uhr
Wie viel schneller/langsamer ist dies als die Ausführung des Raw cp test.log newLog.log
über require('child_process').exec
?
– Lanze
30. Januar 13 um 20:03 Uhr
Brunnen copy
ist im Gegensatz zu einer vollständigen Node.js-Lösung nicht auf Windows portierbar.
– Jean
3. Juli 13 um 18:51 Uhr
Leider ist die Verwendung von Streams auf meinem System im Vergleich zu extrem langsam child_process.execFile('/bin/cp', ['--no-target-directory', source, target])
.
– Robert
25. September 13 um 22:27 Uhr
Ich habe diese Methode verwendet und alles, was ich bekam, war eine leere Datei beim Schreiben. Irgendwelche Ideen warum? fs.createReadStream('./init/xxx.json').pipe(fs.createWriteStream('xxx.json'));
– Timmerz
20. August 14 um 15:23 Uhr
Gleicher Mechanismus, aber dies fügt die 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;
}
}
}
Es ist erwähnenswert, dass das cbCalled-Flag benötigt wird, da Pipe-Fehler einen Fehler in beiden Streams auslösen. Quell- und Zielstreams.
– Gaston Sánchez
26. März 14 um 21:33 Uhr
Wie gehen Sie mit dem Fehler um, wenn die Quelldatei nicht existiert? Die Zieldatei wird in diesem Fall trotzdem erstellt.
– Michel Hua
18. Mai ’14 um 18:04 Uhr
Ich denke ein Fehler in der WriteStream
werde es nur entrohren. Du müsstest anrufen rd.destroy()
du selber. Zumindest ist mir das passiert. Leider gibt es außer dem Quellcode nicht viel Dokumentation.
– Robert
6. August 14 um 5:46 Uhr
was bedeutet die cb
stehen für? Was sollen wir als drittes Argument übergeben?
– SaiyanGirl
26. Februar 15 um 19:29 Uhr
@SaiyanGirl ‘cb’ steht für “Rückruf”. Sie sollten eine Funktion übergeben.
– Brian J. Miller
26. Februar 15 um 22:08 Uhr
Timmerz
Ich konnte die nicht bekommen createReadStream/createWriteStream
Methode funktioniert aus irgendeinem Grund, aber mit der fs-extra npm-Modul hat es auf Anhieb funktioniert. Über den Leistungsunterschied bin ich mir aber nicht sicher.
npm install --save fs-extra
var fs = require('fs-extra');
fs.copySync(path.resolve(__dirname, './init/xxx.json'), 'xxx.json');
Dies ist jetzt die beste Option
– Zain Rizvi
5. Januar 15 um 22:23 Uhr
Die Verwendung von synchronem Code im Knoten beeinträchtigt die Leistung Ihrer Anwendung.
– mvillar
21. Mai ’15 um 6:44 Uhr
Oh bitte … Die Frage ist ungefähr am schnellsten Methode zum Kopieren einer Datei. Während am schnellsten ist immer subjektiv, ich glaube nicht, dass ein synchroner Code hier etwas zu suchen hat.
– sampathris
3. September 15 um 18:25 Uhr
Am schnellsten zu implementieren oder am schnellsten auszuführen? Unterschiedliche Prioritäten bedeuten, dass dies eine gültige Antwort ist.
– Patrick Gunderson
23. September 15 um 20:35 Uhr
fs-extra hat auch asynchrone Methoden, dh fs.copy(src, dst, callback);
und diese sollten die Bedenken von @mvillar lösen.
– Marc Durdin
9. November 15 um 10:49 Uhr
Michail
Seit Node.js 8.5.0 haben wir die neue fs.copyFile und fs.copyFileSync Methoden.
Anwendungsbeispiel:
var fs = require('fs');
// File "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');
});
süß
Schnell geschrieben und bequem zu bedienen, mit Promise- und Error-Management:
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;
});
}
Dasselbe gilt für die async/await-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;
}
}
Was passiert, wenn keine Eingabe mehr vorhanden ist (defekte Netzwerkfreigabe), der Schreibvorgang aber dennoch erfolgreich ist? Wird sowohl „reject“ (vom Lesen) als auch „resolve“ (vom Schreiben) aufgerufen? Was passiert, wenn sowohl Lesen als auch Schreiben fehlschlagen (fehlerhafte Festplattensektoren während des Lesens, volle Festplatte während des Schreibens)? Dann wird zweimal Ablehnen aufgerufen. Eine Promise-Lösung, die auf Mikes Antwort mit einem Flag (leider) basiert, scheint die einzige praktikable Lösung zu sein, die die Fehlerbehandlung richtig berücksichtigt.
– Lekenstein
24. Mai ’15 um 13:15 Uhr
Das Versprechen wird aufgelöst, sobald die Kopie erfolgreich ist. Wenn es abgelehnt wird, ist sein Zustand festgelegt und das mehrmalige Aufrufen von “reject” macht keinen Unterschied.
– gut
24. Mai ’15 um 17:08 Uhr
Ich habe gerade getestet 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);});
und schaute nach spez dazu und du hast recht: Der Versuch, ein gelöstes Versprechen zu lösen oder abzulehnen, hat keine Wirkung. Vielleicht könnten Sie Ihre Antwort erweitern und erklären, warum Sie die Funktion auf diese Weise geschrieben haben? Danke 🙂
– Lekenstein
24. Mai 15 um 22:42 Uhr
Übrigens, close
sollte sein finish
für beschreibbare Streams.
– Lekenstein
25. Mai ’15 um 9:32 Uhr
Und wenn Sie sich fragen, warum Ihre Anwendung nach Pipe-Fehlern nie geschlossen wird /dev/stdin
das ist ein Fehler github.com/joyent/node/issues/25375
– Lekenstein
27. Mai ’15 um 9:26 Uhr
Tester
Nun, normalerweise ist es gut, asynchrone Dateioperationen zu vermeiden. Hier ist das kurze (d. h. keine Fehlerbehandlung) Synchronisierungsbeispiel:
var fs = require('fs');
fs.writeFileSync(targetFile, fs.readFileSync(sourceFile));
Was passiert, wenn keine Eingabe mehr vorhanden ist (defekte Netzwerkfreigabe), der Schreibvorgang aber dennoch erfolgreich ist? Wird sowohl „reject“ (vom Lesen) als auch „resolve“ (vom Schreiben) aufgerufen? Was passiert, wenn sowohl Lesen als auch Schreiben fehlschlagen (fehlerhafte Festplattensektoren während des Lesens, volle Festplatte während des Schreibens)? Dann wird zweimal Ablehnen aufgerufen. Eine Promise-Lösung, die auf Mikes Antwort mit einem Flag (leider) basiert, scheint die einzige praktikable Lösung zu sein, die die Fehlerbehandlung richtig berücksichtigt.
– Lekenstein
24. Mai ’15 um 13:15 Uhr
Das Versprechen wird aufgelöst, sobald die Kopie erfolgreich ist. Wenn es abgelehnt wird, ist sein Zustand festgelegt und das mehrmalige Aufrufen von “reject” macht keinen Unterschied.
– gut
24. Mai ’15 um 17:08 Uhr
Ich habe gerade getestet 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);});
und schaute nach spez dazu und du hast recht: Der Versuch, ein gelöstes Versprechen zu lösen oder abzulehnen, hat keine Wirkung. Vielleicht könnten Sie Ihre Antwort erweitern und erklären, warum Sie die Funktion auf diese Weise geschrieben haben? Danke 🙂
– Lekenstein
24. Mai 15 um 22:42 Uhr
Übrigens, close
sollte sein finish
für beschreibbare Streams.
– Lekenstein
25. Mai ’15 um 9:32 Uhr
Und wenn Sie sich fragen, warum Ihre Anwendung nach Pipe-Fehlern nie geschlossen wird /dev/stdin
das ist ein Fehler github.com/joyent/node/issues/25375
– Lekenstein
27. Mai ’15 um 9:26 Uhr
qntm
Wenn es Ihnen egal ist, dass es asynchron ist, und keine Gigabyte-großen Dateien 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);
}
@RobGleeson und benötigt so viel Speicher wie der Dateiinhalt … Ich bin erstaunt über die Anzahl der Upvotes dort.
– Konstantin
19. Juni 17 um 18:25 Uhr
Ich habe eine Einschränkung “und kopieren keine Gigabyte-großen Dateien” hinzugefügt.
– Andrew Childs
22. November 17 um 17:16 Uhr
Der fs.existsSync
Anruf sollte weggelassen werden. Die Datei könnte in der Zeit zwischen dem verschwinden fs.existsSync
anrufen und die fs.readFileSync
anrufen, was bedeutet, die fs.existsSync
Anruf schützt uns vor nichts.
– qntm
8. August 19 um 13:53 Uhr
Außerdem Rückkehr false
wenn fs.existsSync
scheitert wahrscheinlich an schlechter Ergonomie, weil wenige Verbraucher aus copySync
wird daran denken, den Rückgabewert bei jedem Aufruf manuell zu überprüfen, genauso wenig wie wir es tun fs.writeFileSync
et al.. Das Auslösen einer Ausnahme ist eigentlich vorzuziehen.
– qntm
18. Januar 20 um 15:02 Uhr
Das OP erwähnt nicht ausdrücklich, dass es sich bei seinen Dateien um UTF-8-Text handelt, daher entferne ich die 'utf-8'
Codierung auch aus dem Snippet, was bedeutet, dass dies jetzt für jede Datei funktioniert. data
ist jetzt ein Buffer
kein String
.
– qntm
13. März 20 um 18:06 Uhr
.
Es ist eine gute Frage, obwohl es interessant ist, dass sie 25 positive Stimmen erhält, wenn andere Fragen im ähnlichen Format sofort 3 oder 4 negative Stimmen erhalten, weil sie die SO-“Standards” nicht erfüllen (vielleicht wird das Javascript-Tag von freundlicheren Leuten gecrawlt 🙂
– Ben
11. September 13 um 11:47 Uhr
Meistens sind wir nach Jahren der Normalisierung von Browsern einfach frisch und aufgeregt über dieses ganze „Datei“-Geschäft.
– Erik Reppen
30. Oktober 14 um 17:32 Uhr
Die einzig richtige Antwort auf der Seite ist diese. Keine der anderen Antworten kopiert tatsächlich Dateien. Dateien unter MacOS und Windows haben andere Metadaten, die durch einfaches Kopieren von Bytes verloren gehen. Beispiele für Daten, die von keiner anderen Antwort auf dieser Seite kopiert wurden, Fenster und Mac OS. Selbst unter Unix kopieren die anderen Antworten nicht das Erstellungsdatum, was beim Kopieren einer Datei oft wichtig ist.
– Gman
23. Oktober 18 um 3:58 Uhr