Javascript 在Node.js中复制文件的最快方法
我正在处理的项目(Node.js)意味着大量的文件系统操作(复制、读取、写入等)Javascript 在Node.js中复制文件的最快方法,javascript,node.js,Javascript,Node.js,我正在处理的项目(Node.js)意味着大量的文件系统操作(复制、读取、写入等) 哪些方法最快?使用标准内置方式: 如果您必须支持Node.js的旧版本,下面是在不支持fs.copyFile的版本中如何做到这一点: const fs = require('fs'); fs.createReadStream('test.log').pipe(fs.createWriteStream('newLog.log')); 相同的机制,但这增加了错误处理: function copyFile(source
哪些方法最快?使用标准内置方式: 如果您必须支持Node.js的旧版本,下面是在不支持
fs.copyFile
的版本中如何做到这一点:
const fs = require('fs');
fs.createReadStream('test.log').pipe(fs.createWriteStream('newLog.log'));
相同的机制,但这增加了错误处理:
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;
}
}
}
通常,避免异步文件操作是很好的。以下是简短(即无错误处理)同步示例:
var fs = require('fs');
fs.writeFileSync(targetFile, fs.readFileSync(sourceFile));
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;
}
}
}
由于某种原因,我无法使
createReadStream/createWriteStream
方法工作,但使用npm模块,它立即工作了。不过,我不确定性能的差异
npm安装--保存fs额外信息
var fs = require('fs-extra');
fs.copySync(path.resolve(__dirname, './init/xxx.json'), 'xxx.json');
写得快,使用方便,承诺和错误管理:
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 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;
}
}
如果您不关心它是异步的,并且不复制GB大小的文件,并且不希望仅为单个函数添加另一个依赖项:
function copySync(src, dest) {
var data = fs.readFileSync(src);
fs.writeFileSync(dest, data);
}
,但在复制之前还要检查文件的可见性:
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);
}
});
});
}
,但承诺:
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文件夹不存在,它将自动创建它。另一个答案只会抛出错误
- 它返回一个
,这使得它更容易在更大的项目中使用承诺
- 它允许您复制多个文件,当所有文件都被复制时,承诺就会实现
var onePromise = copyFilePromise("src.txt", "dst.txt");
var anotherPromise = copyMultiFilePromise(new Array(new Array("src1.txt", "dst1.txt"), new Array("src2.txt", "dst2.txt")));
代码:
以前所有不检查源文件是否存在的解决方案都是危险的。。。比如说,
fs.stat(source, function(err,stat) { if (err) { reject(err) }
否则,如果源和目标被错误替换,则场景中存在风险,您的数据将永久丢失而不会发现任何错误。自Node.js 8.5.0以来,我们有了新的和方法 用法示例:
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');
});
使用Node.js的内置复制功能 它同时提供异步和同步版本:
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');
});
对于快速复制,应使用
fs.constants.COPYFILE\u FICLONE
标志。它允许(支持此功能的文件系统)不实际复制文件的内容。只创建了一个新的文件条目,但它指向源文件的“克隆”
什么也不做/少做是做事最快的方式;)
让fs=require(“fs”);
fs.copyFile(
“source.txt”,
“destination.txt”,
fs.constants.COPYFILE_FICLONE,
(错误)=>{
如果(错误){
//TODO:句柄错误
控制台日志(“错误”);
}
控制台日志(“成功”);
}
);
改用承诺:
让fs=require(“fs”);
设util=require(“util”);
让copyFile=util.promisify(fs.copyFile);
复制文件(
“source.txt”,
“destination.txt”,
fs.constants.COPYFILE\u FICLONE
)
.catch(()=>console.log(“错误”))
。然后(()=>console.log(“成功”);
这就是我个人使用Node.js复制文件并替换另一个文件的方法:)您可以使用
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!");
}
});
或
您可能希望使用async/await,因为内置的
fs Promissions API
可以使用节点v10.0.0
例如:
const fs = require('fs')
const copyFile = async (src, dest) => {
await fs.promises.copyFile(src, dest)
}
注:
从节点v11.14.0、v10.17.0开始,API不再是实验性的
更多信息:
我编写了一个小实用程序来测试不同的方法: 用它运行
npx copy-speed-test --source someFile.zip --destination someNonExistentFolder
它使用child_process.exec()执行本机复制,使用fs.copyFile执行复制文件,并使用具有各种不同缓冲区大小的createReadStream(您可以通过在命令行上传递来更改缓冲区大小。有关详细信息,请运行npx copy speed test-h)。请记住,在现实生活中,您希望同时检查
createReadStream
和createWriteStream
是否存在错误,这样您就不会得到一行代码(尽管它仍然一样快)。这比通过require('child\u process')执行原始cp test.log newLog.log
快多少/慢多少.exec
?与完整的Node.js解决方案相反,复制
在Windows上不可移植。不幸的是,在我的系统上,使用streams与子进程.execFile('/bin/cp',['-无目标目录',source,target])相比,速度非常慢。
。我使用了这种方法,在写入时只得到一个空白文件。你知道为什么吗<代码>fs.createReadStream('./init/xxx.json').pipe(fs.createWriteStream('xxx.json'))代码>这是一个很好的问题,但有趣的是,当其他类似格式的问题因为不符合所谓的“标准”而立即获得3或4张反对票时,它获得了25张赞成票(可能javascript标签是由更友善的人抓取的:),大多数情况下,我们只是对整个“文件”感到新鲜和兴奋经过多年的浏览器规范化后的业务。页面上唯一正确的答案是。其他答案实际上都没有复制文件。MacOS和Windows上的文件还有其他元数据,这些元数据仅通过复制字节就丢失了。本页任何其他答案未复制的数据示例,以及。即使在Unix上,其他答案也不会复制创建日期,这在复制文件时通常很重要。值得注意的是,需要cbCalled标志,因为管道错误会在两个流上触发错误。源和目标流。如果源文件不存在,如何处理错误?在这种情况下仍然会创建目标文件。我认为WriteStream
中的错误只会将其取消管道。您必须自己调用rd.destroy()
。至少我是这样的。遗憾的是,除了源代码之外,没有太多文档。cb代表什么?我们应该传递什么作为第三个参数?@SaiyanGirl'cb'代表“回调”。你应该通过一个函数
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!");
}
});
const fs = require('fs')
const copyFile = async (src, dest) => {
await fs.promises.copyFile(src, dest)
}
npx copy-speed-test --source someFile.zip --destination someNonExistentFolder