El proyecto en el que estoy trabajando (node.js) implica muchas operaciones con el sistema de archivos (copia / lectura / escritura, etc.). Me gustaría saber qué métodos son los más rápidos, y me gustaría recibir un consejo. Gracias.
El proyecto en el que estoy trabajando (node.js) implica muchas operaciones con el sistema de archivos (copia / lectura / escritura, etc.). Me gustaría saber qué métodos son los más rápidos, y me gustaría recibir un consejo. Gracias.
Respuestas:
Esta es una buena manera de copiar un archivo en una línea de código utilizando secuencias:
var fs = require('fs');
fs.createReadStream('test.log').pipe(fs.createWriteStream('newLog.log'));
En el nodo v8.5.0, se agregó 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
y createWriteStream
de errores, por lo que no se pueden conseguir una sola línea (aunque seguiría siendo igual de rápido).
cp test.log newLog.log
vía RAW require('child_process').exec
?
copy
no es portátil en Windows, al contrario de una solución completa de Node.js.
child_process.execFile('/bin/cp', ['--no-target-directory', source, target])
.
fs.createReadStream('./init/xxx.json').pipe(fs.createWriteStream('xxx.json'));
Mismo mecanismo, pero esto agrega manejo de errores:
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
solo lo eliminará. Tendrías que llamarte a rd.destroy()
ti mismo. Al menos eso es lo que me pasó. Lamentablemente, no hay mucha documentación, excepto del código fuente.
cb
soporte? ¿Qué debemos pasar como tercer argumento?
No pude hacer que el createReadStream/createWriteStream
método funcionara por alguna razón, pero usando el fs-extra
módulo npm funcionó de inmediato. Sin embargo, no estoy seguro de la diferencia de rendimiento.
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);
, y estos deberían resolver la preocupación de @ mvillar.
Desde Node.js 8.5.0 tenemos los nuevos métodos fs.copyFile y fs.copyFileSync .
Ejemplo de uso:
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()
produce un error al sobrescribir archivos más largos. Cortesía de uv_fs_copyfile()
till Node v8.7.0 (libuv 1.15.0). ver github.com/libuv/libuv/pull/1552
Rápido de escribir y cómodo de usar, con gestión de promesas y errores.
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;
});
}
Lo mismo con la sintaxis 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);});
y busqué las especificaciones sobre esto y tienes razón: intentar resolver o rechazar una promesa resuelta no tiene ningún efecto. ¿Quizás podría extender su respuesta y explicar por qué ha escrito la función de esta manera? Gracias :-)
close
debe ser finish
para las secuencias de escritura.
/dev/stdin
, ese es un error github.com/joyent/node/issues/25375
Bueno, generalmente es bueno evitar las operaciones asíncronas de archivos. Aquí está el breve ejemplo de sincronización (es decir, sin manejo de errores):
var fs = require('fs');
fs.writeFileSync(targetFile, fs.readFileSync(sourceFile));
*Sync
métodos está totalmente en contra de la filosofía de nodejs! También creo que están siendo desaprobados lentamente. La idea general de nodejs es que es de un solo subproceso y está controlada por eventos.
La solución de Mike Schilling con manejo de errores con un atajo para el controlador de eventos de error.
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;
}
}
}
Si no le importa que sea asíncrono, y no esté copiando archivos de tamaño gigabyte, y prefiera no agregar otra dependencia solo para una sola función:
function copySync(src, dest) {
var data = fs.readFileSync(src);
fs.writeFileSync(dest, data);
}
fs.existsSync
llamada debe ser omitida. El archivo podría desaparecer en el tiempo entre la fs.existsSync
llamada y la fs.readFileSync
llamada, lo que significa que la fs.existsSync
llamada no nos protege de nada.
false
si fs.existsSync
falla es probablemente una mala ergonomía porque pocos consumidores copySync
pensarán en inspeccionar manualmente el valor de retorno cada vez que se llame, más de lo que lo hacemos para fs.writeFileSync
et al. . Lanzar una excepción es realmente preferible.
const fs = require("fs");
fs.copyFileSync("filepath1", "filepath2"); //fs.copyFileSync("file1.txt", "file2.txt");
Esto es lo que yo personalmente uso para copiar un archivo y reemplazar otro archivo usando node.js :)
Para copias rápidas, debe usar la fs.constants.COPYFILE_FICLONE
bandera. Permite (para los sistemas de archivos que admiten esto) no copiar realmente el contenido del archivo. Solo se crea una nueva entrada de archivo, pero apunta a un "clon" de Copia en escritura del archivo fuente.
No hacer nada / menos es la forma más rápida de hacer algo;)
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");
}
);
Usando promesas en su lugar:
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
La solución de benweet verifica la visibilidad del archivo antes de la copia:
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);
}
});
});
}
¿Por qué no usar nodejs integrado en la función de copia?
Proporciona versiones asíncronas y sincronizadas:
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
La solución de Mike , pero con promesas:
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);
});
};
Mejora de otra respuesta.
caracteristicas:
promise
, lo que facilita su uso en un proyecto más grande.Uso:
var onePromise = copyFilePromise("src.txt", "dst.txt");
var anotherPromise = copyMultiFilePromise(new Array(new Array("src1.txt", "dst1.txt"), new Array("src2.txt", "dst2.txt")));
Código:
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);
}
Todas las soluciones anteriores que no comprueban la existencia de un archivo fuente son peligrosas ... por ejemplo
fs.stat(source, function(err,stat) { if (err) { reject(err) }
de lo contrario, existe un riesgo en un escenario en caso de que el origen y el destino sean reemplazados por error, sus datos se perderán permanentemente sin notar ningún error.