내가 작업중 인 프로젝트 (node.js)는 파일 시스템 (복사 / 읽기 / 쓰기 등)으로 많은 작업을 의미합니다. 어떤 방법이 가장 빠른지 알고 싶습니다. 기꺼이 조언을 구하십시오. 감사.
내가 작업중 인 프로젝트 (node.js)는 파일 시스템 (복사 / 읽기 / 쓰기 등)으로 많은 작업을 의미합니다. 어떤 방법이 가장 빠른지 알고 싶습니다. 기꺼이 조언을 구하십시오. 감사.
답변:
이것은 스트림을 사용하여 한 줄의 코드로 파일을 복사하는 좋은 방법입니다.
var fs = require('fs');
fs.createReadStream('test.log').pipe(fs.createWriteStream('newLog.log'));
노드 v8.5.0에서 copyFile이 추가되었습니다.
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');
});
createReadStream
와 createWriteStream
오류를 모두 확인하고 싶기 때문에 하나의 라이너를 얻지 못할 것입니다 (여전히 빠르지 만).
cp test.log newLog.log
via를 실행하는 것보다 얼마나 빠르거나 느립니다 require('child_process').exec
?
copy
, 창에 휴대용 전체 Node.js를 솔루션에 위배되지 않습니다.
child_process.execFile('/bin/cp', ['--no-target-directory', source, target])
.
fs.createReadStream('./init/xxx.json').pipe(fs.createWriteStream('xxx.json'));
동일한 메커니즘이지만 오류 처리가 추가됩니다.
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;
}
}
}
WriteStream
의지 의 오류는 파이프를 풀어야 한다고 생각 합니다. 당신은 rd.destroy()
자신 을 호출해야합니다 . 적어도 그것이 저에게 일어난 일입니다. 슬프게도 소스 코드를 제외하고는 문서가 많지 않습니다.
cb
을 의미합니까? 세 번째 논쟁으로 무엇을 전달해야합니까?
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');
fs.copy(src, dst, callback);
, @mvillar의 문제를 해결해야합니다.
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');
});
copyFile()
는 더 긴 파일을 덮어 쓰는 동안 버그가 있음을 명심 하십시오. 씨의 uv_fs_copyfile()
노드 v8.7.0 (libuv 1.15.0)까지. 참조 github.com/libuv/libuv/pull/1552
약속 및 오류 관리 기능으로 빠르고 쓰기 쉽고 사용하기 편리합니다.
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;
}
}
new Promise(function(resolve, reject) { resolve(1); resolve(2); reject(3); reject(4); console.log("DONE"); }).then(console.log.bind(console), function(e){console.log("E", e);});
대한 사양 을 테스트 하고 찾아 보았습니다. 결국 약속을 해결하거나 거부하는 것은 효과가 없습니다. 아마도 당신은 답을 확장하고 왜 이런 식으로 함수를 작성했는지 설명 할 수 있습니까? 감사합니다 :-)
close
이어야합니다 finish
.
/dev/stdin
, 그 버그입니다 github.com/joyent/node/issues/25375은
일반적으로 비동기 파일 작업을 피하는 것이 좋습니다. 다음은 짧은 (즉, 오류 처리 없음) 동기화 예입니다.
var fs = require('fs');
fs.writeFileSync(targetFile, fs.readFileSync(sourceFile));
*Sync
방법을 사용하는 것은 nodejs의 철학에 완전히 반대입니다! 또한 그들은 천천히 사용이 중단되고 있다고 생각합니다. nodejs의 전체 아이디어는 단일 스레드 및 이벤트 중심이라는 것입니다.
오류 처리기를위한 바로 가기가 포함 된 오류 처리 기능이있는 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;
}
}
}
비동기식에 신경 쓰지 않고 기가 바이트 크기의 파일을 복사하지 않고 단일 함수에 대해서만 다른 종속성을 추가하지 않으려는 경우 :
function copySync(src, dest) {
var data = fs.readFileSync(src);
fs.writeFileSync(dest, data);
}
fs.existsSync
호출은 생략한다. fs.existsSync
통화와 통화 사이에 파일이 사라질 수 있습니다. fs.readFileSync
즉, fs.existsSync
통화가 우리를 보호하지 못합니다.
false
경우 fs.existsSync
에는 인체 공학적으로 열악한 인체 공학적 문제가 발생할 copySync
수 있습니다 fs.writeFileSync
. . 실제로 예외를 던지는 것이 좋습니다.
const fs = require("fs");
fs.copyFileSync("filepath1", "filepath2"); //fs.copyFileSync("file1.txt", "file2.txt");
이것은 개인적으로 파일을 복사하고 node.js를 사용하여 다른 파일을 대체하는 데 사용합니다 :)
빠른 복사를 위해서는 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"));
fs.promises.copyFile
복사하기 전에 파일의 가시성을 검사하는 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);
}
});
});
}
내장 된 복사 기능으로 nodejs를 사용하지 않는 이유는 무엇입니까?
비동기 및 동기화 버전을 모두 제공합니다.
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
Mike의 솔루션 이지만 약속이 있습니다.
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);
});
};
다른 답변의 개선.
풍모:
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);
}
소스 파일의 존재를 확인하지 않는 위의 모든 솔루션은 위험합니다 ... 예 :
fs.stat(source, function(err,stat) { if (err) { reject(err) }
그렇지 않으면 소스와 대상이 실수로 교체 된 경우 시나리오에서 위험이 있으며 오류를 알리지 않고 데이터가 영구적으로 손실됩니다.