Proyek yang sedang saya kerjakan (node.js) menyiratkan banyak operasi dengan sistem file (menyalin / membaca / menulis dll). Saya ingin tahu metode mana yang paling cepat, dan saya senang mendapatkan saran. Terima kasih.
Proyek yang sedang saya kerjakan (node.js) menyiratkan banyak operasi dengan sistem file (menyalin / membaca / menulis dll). Saya ingin tahu metode mana yang paling cepat, dan saya senang mendapatkan saran. Terima kasih.
Jawaban:
Ini adalah cara yang baik untuk menyalin file dalam satu baris kode menggunakan stream:
var fs = require('fs');
fs.createReadStream('test.log').pipe(fs.createWriteStream('newLog.log'));
Dalam simpul v8.5.0, copyFile ditambahkan
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
dan juga createWriteStream
kesalahannya, sehingga Anda tidak akan mendapatkan satu kalimat (meskipun itu akan tetap sama cepatnya).
cp test.log newLog.log
melalui require('child_process').exec
?
copy
tidak portabel di Window, bertentangan dengan solusi Node.js penuh.
child_process.execFile('/bin/cp', ['--no-target-directory', source, target])
.
fs.createReadStream('./init/xxx.json').pipe(fs.createWriteStream('xxx.json'));
Mekanisme yang sama, tetapi ini menambahkan penanganan kesalahan:
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
hanya akan menghapusnya. Anda harus menyebut rd.destroy()
diri Anda sendiri. Setidaknya itulah yang terjadi pada saya. Sayangnya tidak ada banyak dokumentasi kecuali dari kode sumber.
cb
berdiri? apa yang harus kita sampaikan sebagai argumen ketiga?
Saya tidak bisa mendapatkan createReadStream/createWriteStream
metode ini bekerja karena alasan tertentu, tetapi menggunakan fs-extra
modul npm itu berhasil segera. Saya tidak yakin dengan perbedaan kinerja.
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);
, dan ini harus menyelesaikan masalah @ mvillar.
Sejak Node.js 8.5.0 kami memiliki fs.copyFile baru dan fs.copyFileSync metode.
Contoh Penggunaan:
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()
disadap saat menimpa file yang lebih panjang. Atas perkenan uv_fs_copyfile()
sampai Node v8.7.0 (libuv 1.15.0). lihat github.com/libuv/libuv/pull/1552
Cepat untuk menulis dan nyaman digunakan, dengan manajemen janji dan kesalahan.
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;
});
}
Sama dengan sintaks 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);});
dan mencari spesifikasi ini dan Anda benar: Mencoba untuk menyelesaikan atau menolak janji yang telah diselesaikan tidak akan berpengaruh. Mungkin Anda bisa memperluas jawaban dan menjelaskan mengapa Anda telah menulis fungsi dengan cara ini? Terima kasih :-)
close
harus finish
untuk stream yang dapat ditulisi.
/dev/stdin
, itu adalah bug github.com/joyent/node/issues/25375
Yah, biasanya ada baiknya menghindari operasi file yang tidak sinkron. Berikut adalah contoh sinkronisasi pendek (mis. Tidak ada penanganan kesalahan):
var fs = require('fs');
fs.writeFileSync(targetFile, fs.readFileSync(sourceFile));
*Sync
metode ini benar-benar bertentangan dengan filosofi nodejs '! Saya juga berpikir mereka perlahan-lahan ditinggalkan. Seluruh ide dari nodejs adalah bahwa itu single threaded dan event-driven.
Solusi Mike Schilling dengan penanganan kesalahan dengan jalan pintas untuk penangan peristiwa kesalahan.
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;
}
}
}
Jika Anda tidak peduli itu async, dan tidak menyalin file berukuran gigabyte, dan lebih suka tidak menambahkan ketergantungan lain hanya untuk satu fungsi:
function copySync(src, dest) {
var data = fs.readFileSync(src);
fs.writeFileSync(dest, data);
}
fs.existsSync
panggilan harus dihilangkan. File dapat hilang pada waktu antara fs.existsSync
panggilan dan fs.readFileSync
panggilan, yang berarti fs.existsSync
panggilan tidak melindungi kita dari apa pun.
false
jika fs.existsSync
gagal cenderung ergonomi yang buruk karena hanya sedikit konsumen yang copySync
akan berpikir untuk memeriksa secara manual nilai pengembalian setiap kali disebut, lebih dari yang kami lakukan untuk fs.writeFileSync
et al. . Melempar pengecualian sebenarnya lebih disukai.
const fs = require("fs");
fs.copyFileSync("filepath1", "filepath2"); //fs.copyFileSync("file1.txt", "file2.txt");
Inilah yang saya pribadi gunakan untuk menyalin file dan mengganti file lain menggunakan node.js :)
Untuk salinan cepat Anda harus menggunakan fs.constants.COPYFILE_FICLONE
bendera. Ini memungkinkan (untuk sistem file yang mendukung ini) untuk tidak benar-benar menyalin konten file. Hanya entri file baru yang dibuat, tetapi itu menunjuk ke Copy-on-Write "klon" dari file sumber.
Untuk tidak melakukan apa-apa / kurang adalah cara tercepat untuk melakukan sesuatu;)
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");
}
);
Sebaliknya, menggunakan janji:
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
solusi benweet memeriksa visibilitas file sebelum menyalin:
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);
}
});
});
}
Mengapa tidak menggunakan nodejs built in fungsi salin?
Ini memberikan versi async dan sinkronisasi:
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
Solusi Mike , tetapi dengan janji:
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);
});
};
Perbaikan satu jawaban lainnya.
Fitur:
promise
, yang membuatnya lebih mudah digunakan dalam proyek yang lebih besar.Pemakaian:
var onePromise = copyFilePromise("src.txt", "dst.txt");
var anotherPromise = copyMultiFilePromise(new Array(new Array("src1.txt", "dst1.txt"), new Array("src2.txt", "dst2.txt")));
Kode:
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);
}
semua solusi di atas yang tidak memeriksa keberadaan file sumber berbahaya ... mis
fs.stat(source, function(err,stat) { if (err) { reject(err) }
jika tidak ada risiko dalam skenario jika sumber dan target diganti secara tidak sengaja, data Anda akan hilang secara permanen tanpa memperhatikan adanya kesalahan.