在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.copyFile和fs.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) }
否则在场景中有一个风险,如果源和目标是由一个错误代替,你的数据将永久丢失,不会有任何错误。