wake-up-neo.net

Der schnellste Weg, um eine Datei in node.js zu kopieren

Ein Projekt, an dem ich arbeite (node.js), beinhaltet viele Operationen mit dem Dateisystem (Kopieren/Lesen/Schreiben usw.). Ich würde gerne wissen, welche Methoden am schnellsten sind, und würde mich über Ratschläge freuen.

399
bonbonez

Dies ist eine gute Möglichkeit, eine Datei in einer Codezeile mithilfe von Streams 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');
});
585

Gleicher Mechanismus, aber dies fügt 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;
    }
  }
}
285
Mike Schilling

Ich konnte die createReadStream/createWriteStream-Methode aus irgendeinem Grund nicht zum Laufen bringen, aber mit dem fs-extra npm-Modul funktionierte es sofort. Ich bin mir des Leistungsunterschieds jedoch nicht sicher.

fs-extra

npm install --save fs-extra

var fs = require('fs-extra');

fs.copySync(path.resolve(__dirname,'./init/xxx.json'), 'xxx.json');
131
Timmerz

Seit Node.js 8.5.0 gibt es die neuen fs.copyFile und fs.copyFileSync - Methoden.

Verwendungsbeispiel:

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');
});
97
Mikhail

Schnell zu schreiben und bequem zu bedienen, mit Versprechungs- 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;
  });
}

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;
  }
}
71
benweet

Normalerweise ist es gut, asynchrone Dateivorgänge zu vermeiden. Hier ist das kurze Sync-Beispiel (d. H. Keine Fehlerbehandlung):

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

Wenn Sie sich nicht darum kümmern, dass es asynchron ist, und keine Dateien in Gigabyte-Größe kopieren, sondern eine weitere Abhängigkeit nur für eine einzelne Funktion hinzufügen:

function copySync(src, dest) {
  if (!fs.existsSync(src)) {
    return false;
  }

  var data = fs.readFileSync(src, 'utf-8');
  fs.writeFileSync(dest, data);
}
18
Andrew Childs

Die Lösung von Mike Schilling mit Fehlerbehandlung mit einer Abkürzung 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;
    }
  }
}
18
Jens Hauke

die Lösung von benweet prü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);
            }
        });
    });
}
1
Pedro Rodrigues

Verbesserung einer anderen Antwort.

Eigenschaften:

  • Wenn die DST-Ordner nicht vorhanden sind, werden sie automatisch erstellt. Die andere Antwort wird nur Fehler werfen.
  • Es gibt eine promise zurück, die die Verwendung in einem größeren Projekt erleichtert.
  • Sie können mehrere Dateien kopieren, und das Versprechen wird gemacht, wenn alle kopiert werden.

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);
}
0
fzyzcjy

Mikes Lösung , aber mit Versprechen:

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);
    });
};
0
mpen

Warum verwenden Sie nicht die eingebauten Kopierfunktionen von nodejs?

Es bietet sowohl eine async- als auch eine sync-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

0
Xin Wang

alle obigen Lösungen, die das Vorhandensein einer Quelldatei nicht prüfen, sind gefährlich ... z.

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

andernfalls besteht in einem Szenario ein Risiko für den Fall, dass Quelle und Ziel durch einen Fehler ersetzt werden.

0
stancikcom

Für schnelle Kopien sollten Sie das Flag fs.constants.COPYFILE_FICLONE verwenden. Es ermöglicht (für Dateisysteme, die dies unterstützen), den Inhalt der Datei nicht wirklich zu kopieren. Nichts 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");
  }
);

Stattdessen Versprechen verwenden:

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"));
0
chpio