在node.js中复制文件的最快方法

我在(node.js)工作的项目意味着很多文件系统的操作(复制/读取/写入等)。 我想知道,什么方法是最快的,我会很乐意提供一些build议。

这是使用stream在一行代码中复制文件的好方法:

var fs = require('fs'); fs.createReadStream('test.log').pipe(fs.createWriteStream('newLog.log')); 

相同的机制,但是这增加了error handling:

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

我无法得到createReadStream/createWriteStream方法工作,但使用fs-extra npm模块它马上工作。 我不确定性能差异。

FS-EXTRA

npm install --save fs-extra

 var fs = require('fs-extra'); fs.copySync(path.resolve(__dirname,'./init/xxx.json'), 'xxx.json'); 

快速写入和使用方便,承诺和错误pipe理。

 function copyFile(source, target) { return new Promise(function(resolve, reject) { var rd = fs.createReadStream(source); rd.on('error', rejectCleanup); var wr = fs.createWriteStream(target); wr.on('error', rejectCleanup); function rejectCleanup(err) { rd.destroy(); wr.end(); reject(err); } wr.on('finish', resolve); rd.pipe(wr); }); } 

那么,通常避免asynchronous文件操作是很好的做法。 这里是简短的(即没有error handling)同步的例子:

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

Mike Schilling的解决scheme,通过错误事件处理程序的快捷方式进行error handling。

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

从Node.js 8.5.0开始,我们有了新的fs.copyFilefs.copyFileSync方法。

用法示例:

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

如果你不关心它是asynchronous的,而不是只为一个函数添加另一个依赖:

 function copySync(src, dest) { if (!fs.existsSync(src)) { return false; } var data = fs.readFileSync(src, 'utf-8'); fs.writeFileSync(dest, data); } 

benweet解决scheme在复制之前检查文件的可见性:

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

迈克的解决scheme ,但承诺:

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

改进另一个答案。

特征:

  • 如果dst文件夹不存在,它会自动创build它。 另一个答案只会抛出错误。
  • 它返回一个promise ,这使得在一个更大的项目中使用起来更容易。
  • 它允许你复制多个文件,当所有文件都被复制时,这个承诺就会完成。

用法:

 var onePromise = copyFilePromise("src.txt", "dst.txt"); var anotherPromise = copyMultiFilePromise(new Array(new Array("src1.txt", "dst1.txt"), new Array("src2.txt", "dst2.txt"))); 

码:

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

以上所有不检查源文件存在的解决scheme都是危险的

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

否则在场景中有一个风险,如果源和目标是由一个错误代替,你的数据将永久丢失,不会有任何错误。