我正在工作的项目(node.js)意味着文件系统的许多操作(复制/读/写等)。我想知道,哪种方法最快,我很乐意提供一些建议。
答案 0 :(得分:608)
这是使用流在一行代码中复制文件的好方法:
var fs = require('fs');
fs.createReadStream('test.log').pipe(fs.createWriteStream('newLog.log'));
In node v8.5.0, copyFile was added
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');
});
答案 1 :(得分:287)
相同的机制,但这增加了错误处理:
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;
}
}
}
答案 2 :(得分:133)
由于某些原因,我无法使createReadStream/createWriteStream
方法正常工作,但使用fs-extra
npm模块可以立即使用它。我不确定性能差异。
npm install --save fs-extra
var fs = require('fs-extra');
fs.copySync(path.resolve(__dirname,'./init/xxx.json'), 'xxx.json');
答案 3 :(得分:107)
自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');
});
答案 4 :(得分:71)
编写速度快,使用方便,承诺和错误管理。
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;
});
}
与async / await语法相同:
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;
}
}
答案 5 :(得分:38)
嗯,通常最好避免异步文件操作。这是短的(即没有错误处理)同步示例:
var fs = require('fs');
fs.writeFileSync(targetFile, fs.readFileSync(sourceFile));
答案 6 :(得分:18)
Mike Schilling的错误处理解决方案,其中包含错误事件处理程序的快捷方式。
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;
}
}
}
答案 7 :(得分:18)
如果您不关心它是异步的,并且没有复制千兆字节大小的文件,并且宁愿不为单个函数添加另一个依赖项:
function copySync(src, dest) {
if (!fs.existsSync(src)) {
return false;
}
var data = fs.readFileSync(src, 'utf-8');
fs.writeFileSync(dest, data);
}
答案 8 :(得分:1)
benweet的解决方案在复制之前检查文件的可见性:
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);
}
});
});
}
答案 9 :(得分:0)
我写了一个小工具来测试不同的方法:
https://www.npmjs.com/package/copy-speed-test
运行它
npx copy-speed-test --source someFile.zip --destination someNonExistentFolder
它使用 child_process.exec() 进行本地复制,使用 fs.copyFile 进行复制文件,并使用具有各种不同缓冲区大小的 createReadStream(您可以通过在命令行上传递它们来更改缓冲区大小。运行 npx copy -speed-test -h 了解更多信息)。
答案 10 :(得分:0)
您可能要使用异步/等待,因为内置node v10.0.0
可以使用fs Promises API
。
示例:
const fs = require('fs')
const copyFile = async (src, dest) => {
await fs.promises.copyFile(src, dest)
}
注意:
从
node v11.14.0, v10.17.0
开始,该API不再处于实验阶段。
更多信息:
答案 11 :(得分:0)
您可以使用fs-extra
模块很容易地做到这一点:
const fse = require('fs-extra');
let srcDir = 'path/to/file';
let destDir = 'pat/to/destination/directory';
fse.moveSync(srcDir, destDir, function (err) {
// To move a file permanently from a directory
if (err) {
console.error(err);
} else {
console.log("success!");
}
});
或
fse.copySync(srcDir, destDir, function (err) {
// To copy a file from a directory
if (err) {
console.error(err);
} else {
console.log("success!");
}
});
答案 12 :(得分:0)
foo()
这是我个人用来复制文件并使用node.js替换另一个文件的方法:)
答案 13 :(得分:0)
对于快速复印,应使用fs.constants.COPYFILE_FICLONE
标志。它允许(对于支持此功能的文件系统)实际上不复制文件的内容。仅创建了一个新文件条目,但它指向源文件的Copy-on-Write“克隆”。
什么都不做/更少是做某事的最快方法;)
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");
}
);
改用诺言:
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"));
答案 14 :(得分:0)
为什么不使用内置复制功能的nodej?
它同时提供异步和同步版本:
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
答案 15 :(得分:0)
以上所有不检查源文件是否存在的解决方案都是危险的......例如。
fs.stat(source, function(err,stat) { if (err) { reject(err) }
否则在某种情况下存在风险,如果源和目标被错误替换,您的数据将永久丢失而不会发现任何错误。
答案 16 :(得分:0)
改进另一个答案。
特点:
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);
}
答案 17 :(得分:0)
Mike's solution,但有承诺:
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);
});
};