Projekt, nad którym pracuję (node.js) zakłada wiele operacji z systemem plików (kopiowanie / odczytywanie / zapisywanie itp.). Chciałbym wiedzieć, które metody są najszybsze i chętnie udzielę porady. Dzięki.
Projekt, nad którym pracuję (node.js) zakłada wiele operacji z systemem plików (kopiowanie / odczytywanie / zapisywanie itp.). Chciałbym wiedzieć, które metody są najszybsze i chętnie udzielę porady. Dzięki.
Odpowiedzi:
Jest to dobry sposób na skopiowanie pliku w jednym wierszu kodu przy użyciu strumieni:
var fs = require('fs');
fs.createReadStream('test.log').pipe(fs.createWriteStream('newLog.log'));
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');
});
createReadStreami createWriteStreambłędy, abyś nie dostał linijki (choć byłoby to tak samo szybkie).
cp test.log newLog.logprzez require('child_process').exec?
copynie jest przenośny w systemie Windows, w przeciwieństwie do pełnego rozwiązania Node.js.
child_process.execFile('/bin/cp', ['--no-target-directory', source, target]).
fs.createReadStream('./init/xxx.json').pipe(fs.createWriteStream('xxx.json'));
Ten sam mechanizm, ale dodaje obsługę błędów:
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;
}
}
}
WriteStreamspowoduje tylko usunięcie z niego zapisów. Musisz zadzwonić do rd.destroy()siebie. Przynajmniej tak mi się stało. Niestety nie ma zbyt wiele dokumentacji oprócz kodu źródłowego.
cbskrót co powinniśmy przekazać jako trzeci argument?
Z createReadStream/createWriteStreamjakiegoś powodu nie byłem w stanie uruchomić tej metody, ale przy użyciu fs-extramodułu npm zadziałało od razu. Nie jestem jednak pewien różnicy w wydajności.
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);powinny one rozwiązać problem @ mvillar.
Od wersji Node.js 8.5.0 mamy nowe metody fs.copyFile i fs.copyFileSync .
Przykład użycia:
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()jest to błąd podczas nadpisywania dłuższych plików. Dzięki uprzejmości uv_fs_copyfile()till Node v8.7.0 (libuv 1.15.0). patrz github.com/libuv/libuv/pull/1552
Szybki do pisania i wygodny w użyciu, z zarządzaniem obietnicami i błędami.
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;
});
}
To samo dotyczy składni 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);});i sprawdziłem specyfikację w tym zakresie i masz rację: próba rozwiązania lub odrzucenia rozwiązanej obietnicy nie ma żadnego efektu. Być może mógłbyś rozszerzyć swoją odpowiedź i wyjaśnić, dlaczego napisałeś tę funkcję w ten sposób? Dzięki :-)
closepowinno być finishdla zapisywalnych strumieni.
/dev/stdin, jest to błąd github.com/joyent/node/issues/25375
Zazwyczaj dobrze jest unikać asynchronicznych operacji na plikach. Oto krótki przykład synchronizacji (tzn. Bez obsługi błędów):
var fs = require('fs');
fs.writeFileSync(targetFile, fs.readFileSync(sourceFile));
*Syncmetod jest całkowicie sprzeczne z filozofią Nodejsa! Myślę też, że są powoli przestarzałe. Cała idea nodejs polega na tym, że jest jednowątkowy i sterowany zdarzeniami.
Rozwiązanie Mike'a Schillinga z obsługą błędów ze skrótem do obsługi zdarzenia błędu.
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;
}
}
}
Jeśli nie obchodzi Cię asynchronizacja i nie kopiujesz plików o wielkości gigabajtów, a raczej nie dodałbyś innej zależności tylko dla jednej funkcji:
function copySync(src, dest) {
var data = fs.readFileSync(src);
fs.writeFileSync(dest, data);
}
fs.existsSyncPołączenie powinno być pominięte. Plik może zniknąć w czasie między fs.existsSyncrozmową a fs.readFileSyncrozmową, co oznacza, że fs.existsSyncrozmowa nie chroni nas przed niczym.
falseprzypadku fs.existsSyncniepowodzenia jest prawdopodobnie słabą ergonomią, ponieważ niewielu konsumentów copySyncpomyśli o ręcznym sprawdzaniu wartości zwrotu za każdym razem, gdy jest wywoływane, podobnie jak my fs.writeFileSync i inni. . Zgłaszanie wyjątku jest właściwie preferowane.
const fs = require("fs");
fs.copyFileSync("filepath1", "filepath2"); //fs.copyFileSync("file1.txt", "file2.txt");
To jest to, czego osobiście używam, aby skopiować plik i zastąpić inny plik za pomocą node.js :)
W przypadku szybkich kopii należy użyć fs.constants.COPYFILE_FICLONEflagi. Pozwala (dla systemów plików, które to obsługują) nie kopiować zawartości pliku. Tworzony jest tylko nowy wpis pliku, ale wskazuje on opcję Kopiuj przy zapisie „klon” pliku źródłowego .
Nic nie robić / to najszybszy sposób na zrobienie czegoś;)
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");
}
);
Zamiast tego użyj obietnic:
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
rozwiązanie benweet sprawdzające widoczność pliku przed kopiowaniem:
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);
}
});
});
}
Dlaczego nie skorzystać z wbudowanej funkcji kopiowania nodejs?
Zapewnia zarówno wersję asynchroniczną, jak i synchronizacyjną:
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
Rozwiązanie Mike'a , ale z obietnicami:
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);
});
};
Ulepszenie jednej innej odpowiedzi.
Funkcje:
promise, co ułatwia użycie w większym projekcie.Stosowanie:
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);
}
wszystkie powyższe rozwiązania, które nie sprawdzają istnienia pliku źródłowego, są niebezpieczne ... np
fs.stat(source, function(err,stat) { if (err) { reject(err) }
w przeciwnym razie istnieje ryzyko w przypadku, gdy źródło i cel zostaną omyłkowo zastąpione, dane zostaną trwale utracone bez zauważenia błędu.