Der schnellste Weg, eine Datei in Node.js zu kopieren

Lesezeit: 8 Minuten

Der schnellste Weg eine Datei in Nodejs zu kopieren
Bonbonz

Das Projekt, an dem ich arbeite (Node.js), impliziert viele Operationen mit dem Dateisystem (Kopieren, Lesen, Schreiben usw.).

Welche Methoden sind die schnellsten?

  • 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


Der schnellste Weg eine Datei in Nodejs zu kopieren
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

Der schnellste Weg eine Datei in Nodejs zu kopieren
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

1643910912 968 Der schnellste Weg eine Datei in Nodejs zu kopieren
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');
});

1643910912 683 Der schnellste Weg eine Datei in Nodejs zu kopieren
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/stdindas ist ein Fehler github.com/joyent/node/issues/25375

    – Lekenstein

    27. Mai ’15 um 9:26 Uhr

1643910913 649 Der schnellste Weg eine Datei in Nodejs zu kopieren
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/stdindas ist ein Fehler github.com/joyent/node/issues/25375

    – Lekenstein

    27. Mai ’15 um 9:26 Uhr

1643910913 796 Der schnellste Weg eine Datei in Nodejs zu kopieren
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 Bufferkein String.

    – qntm

    13. März 20 um 18:06 Uhr

.

758330cookie-checkDer schnellste Weg, eine Datei in Node.js zu kopieren

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy