Üzerinde çalıştığım proje (node.js) dosya sistemi (kopyalama / okuma / yazma vb.) Hangi yöntemlerin en hızlı olduğunu bilmek istiyorum ve tavsiye almaktan mutluluk duyarım. Teşekkürler.
Üzerinde çalıştığım proje (node.js) dosya sistemi (kopyalama / okuma / yazma vb.) Hangi yöntemlerin en hızlı olduğunu bilmek istiyorum ve tavsiye almaktan mutluluk duyarım. Teşekkürler.
Yanıtlar:
Bu, akışları kullanarak bir dosyayı bir kod satırında kopyalamanın iyi bir yoludur:
var fs = require('fs');
fs.createReadStream('test.log').pipe(fs.createWriteStream('newLog.log'));
V8.5.0 düğümünde copyFile eklendi
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
ve hem de createWriteStream
hataları kontrol etmek isteyeceğinizi unutmayın , bu yüzden tek bir astar elde edemezsiniz (yine de aynı derecede hızlı olacaktır).
cp test.log newLog.log
yoldan yürütmekten ne kadar hızlı / yavaş require('child_process').exec
?
copy
, tam bir Node.js çözümünün aksine, pencerede taşınabilir değildir.
child_process.execFile('/bin/cp', ['--no-target-directory', source, target])
.
fs.createReadStream('./init/xxx.json').pipe(fs.createWriteStream('xxx.json'));
Aynı mekanizma, ancak bu hata işleme ekler:
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
sadece onu açmak olacaktır. rd.destroy()
Kendinizi aramalısınız . En azından başıma bu geldi. Ne yazık ki kaynak kodu dışında çok fazla belge yok.
cb
? üçüncü argüman olarak ne geçmeliyiz?
Bir createReadStream/createWriteStream
nedenden dolayı yöntemi çalıştıramadım, ancak fs-extra
npm modülünü kullanarak hemen çalıştı. Yine de performans farkından emin değilim.
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);
extra'nun da eşzamansız yöntemleri vardır ve bunlar @ mvillar'ın endişesini çözmelidir.
Node.js 8.5.0'dan beri yeni fs.copyFile ve fs.copyFileSync yöntemlerimiz var.
Kullanım Örneği:
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()
, daha uzun dosyaların üzerine yazarken hata olduğunu unutmayın . Nezaket uv_fs_copyfile()
Düğümü v8.7.0 (libuv 1.15.0) kadar. bkz. github.com/libuv/libuv/pull/1552
Hızlı yazma ve kullanımı kolay, söz ve hata yönetimi ile.
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;
});
}
Eşzamansız / sözdizimi ile aynı:
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);});
ve başını kaldırdı spesifikasyonları bu konuda evet haklısınız: kararlılığının çalışılıyor veya çözülmesi söz etkisi yoktur reddeder. Belki cevabınızı uzatabilir ve işlevi neden bu şekilde yazdığınızı açıklayabilirsiniz? Teşekkürler :-)
close
olmalıdır finish
.
/dev/stdin
, bu bir hata github.com/joyent/node/issues/25375
Genellikle, eşzamansız dosya işlemlerinden kaçınmak iyidir. Kısa (yani hata işleme yok) senkronizasyon örneği:
var fs = require('fs');
fs.writeFileSync(targetFile, fs.readFileSync(sourceFile));
*Sync
yöntemleri kullanmak tamamen düğümlerin felsefesine karşıdır! Ayrıca yavaş yavaş reddedildiklerini düşünüyorum. Düğümün tüm fikri, tek dişli ve olay güdümlü olmasıdır.
Mike Schilling'in hata işleme çözümü, hata olay işleyicisi için bir kısayol ile.
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;
}
}
}
Eşzamansız olmasını umursamıyorsanız ve gigabayt boyutlu dosyaları kopyalamıyorsanız ve yalnızca tek bir işlev için başka bir bağımlılık eklemek istemiyorsanız:
function copySync(src, dest) {
var data = fs.readFileSync(src);
fs.writeFileSync(dest, data);
}
fs.existsSync
Çağrı çıkarılmalıdır. Dosya, fs.existsSync
çağrı ve çağrı arasındaki sürede kaybolabilir fs.readFileSync
, yani fs.existsSync
çağrı bizi hiçbir şeyden korumaz.
false
eğer fs.existsSync
başarısız olursa geri dönmek muhtemelen düşük ergonomiye sahiptir, çünkü az sayıda tüketici copySync
her çağrıldığında geri dönüş değerini el ile incelemeyi düşünecektir fs.writeFileSync
. . Bir istisna atmak aslında tercih edilir.
const fs = require("fs");
fs.copyFileSync("filepath1", "filepath2"); //fs.copyFileSync("file1.txt", "file2.txt");
Kişisel olarak bir dosyayı kopyalamak ve node.js kullanarak başka bir dosyayı değiştirmek için kullandığım şey budur :)
Hızlı kopyalar için fs.constants.COPYFILE_FICLONE
bayrağı kullanmalısınız . (Bunu destekleyen dosya sistemleri için) dosyanın içeriğini gerçekten kopyalamamasına izin verir. Yalnızca yeni bir dosya girişi oluşturulur, ancak Yazarken Kopyala'yı gösterir kaynak dosyanın "klonunu" gösterir.
Hiçbir şey / daha az şey yapmak, bir şey yapmanın en hızlı yoludur;)
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");
}
);
Bunun yerine vaatleri kullanmak:
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
kopyadan önce dosyanın görünürlüğünü kontrol eden benweet çözümü:
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);
}
});
});
}
Kopyalama işlevinde yerleşik nodejs neden kullanılmıyor?
Hem eşzamansız hem de eşitleme sürümünü sağlar:
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'ın çözümü , ancak vaatlerle:
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);
});
};
Bir diğer cevabın geliştirilmesi.
Özellikleri:
promise
, bu da daha büyük bir projede kullanımını kolaylaştırır.Kullanımı:
var onePromise = copyFilePromise("src.txt", "dst.txt");
var anotherPromise = copyMultiFilePromise(new Array(new Array("src1.txt", "dst1.txt"), new Array("src2.txt", "dst2.txt")));
Kod:
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);
}
Kaynak dosyanın varlığını kontrol etmeyen yukarıdaki tüm çözümler tehlikelidir ... örn.
fs.stat(source, function(err,stat) { if (err) { reject(err) }
Aksi takdirde, kaynak ve hedefin bir hata ile değiştirilmesi durumunda senaryoda bir risk vardır, verileriniz herhangi bir hata fark etmeden kalıcı olarak kaybolacaktır.