Copia y desplazamiento de archivos

Las principales operaciones con archivos a nivel del sistema de archivos son copiar y mover. Para estos fines, MQL5 implementa dos funciones con prototipos idénticos.

bool FileCopy(const string source, int flag, const string destination, int mode)

La función copia el archivo source en el archivo destination. Ambos parámetros mencionados pueden contener sólo nombres de archivo, o nombres junto con rutas con prefijo (jerarquías de carpetas) en los entornos virtuales de MQL5. Los parámetros flag y mode determinan en qué carpeta de trabajo se busca el archivo de origen y cuál es la carpeta de trabajo de destino: 0 significa que se trata de una carpeta de la instancia local actual del terminal (o del agente del probador, si el programa se está ejecutando en el probador), y el valor FILE_COMMON indica la carpeta común para todos los terminales.

Además, en el parámetro mode puede especificar opcionalmente la constante FILE_REWRITE (si necesita combinar FILE_REWRITE y FILE_COMMON; esto se hace utilizando el operador a nivel de bits OR (|)). En ausencia de FILE_REWRITE está prohibido copiar sobre un archivo existente. En otras palabras: si el archivo con la ruta y el nombre especificados en el parámetro destination ya existe, debe confirmar su intención de sobrescribirlo estableciendo FILE_REWRITE. Si no se hace así, la llamada a la función fallará.

La función devuelve true si se completa con éxito, o false en caso de error.

La copia puede fallar si el archivo de origen o destino está ocupado (abierto) por otro proceso.

Al copiar archivos suelen guardarse sus metadatos (hora de creación, derechos de acceso, flujos de datos alternativos). Si necesita realizar una copia «pura» únicamente de los datos del propio archivo, puede utilizar las llamadas sucesivas FileLoad y FileSave, véase Escritura y lectura de archivos en modo simplificado.

bool FileMove(const string source, int flag, const string destination, int mode)

La función mueve o renombra un archivo. La ruta de origen y el nombre se especifican en el parámetro source, y la ruta de destino y el nombre se especifican en destination.

La lista de parámetros y sus principios de funcionamiento son los mismos que para la función FileCopy. A grandes rasgos, FileMove hace el mismo trabajo que FileCopy, pero además borra el archivo original después de que la copia se realiza correctamente.

Vamos a aprender a trabajar con funciones en la práctica utilizando el script FileCopy.mq5. Tiene dos variables con los nombres de los archivos. Ambos archivos no existen cuando se ejecuta el script.

const string source = "MQL5Book/source";
const string destination = "MQL5Book/destination";

En OnStart realizamos una secuencia de acciones según un escenario sencillo. En primer lugar, intentamos copiar el archivo source del directorio de trabajo local al archivo destination del directorio general. Como era de esperar, obtenemos false, y el código de error en _LastError será 5019 (FILE_NOT_EXIST).

void OnStart()
{
   PRTF(FileCopy(source0destinationFILE_COMMON)); // false / FILE_NOT_EXIST(5019)
   ...

Por lo tanto, crearemos un archivo fuente de la forma habitual, escribiremos algunos datos y los descargaremos en el disco.

   int handle = PRTF(FileOpen(sourceFILE_TXT | FILE_WRITE)); // 1
   PRTF(FileWriteString(handle"Test Text\n")); // 22
   FileFlush(handle);

Como el archivo se dejó abierto y no se especificó el permiso FILE_SHARE_READ al abrirlo, el acceso al mismo de otras formas (saltándose el manejador) sigue bloqueado. Por lo tanto, el siguiente intento de copia volverá a fallar.

   PRTF(FileCopy(source0destinationFILE_COMMON)); // false / CANNOT_OPEN_FILE(5004)

Vamos a cerrar el archivo e intentarlo de nuevo. Pero antes, obtengamos las propiedades del archivo resultante en el registro: cuándo se creó y cuándo se modificó. Ambas propiedades contendrán la marca de tiempo actual de su ordenador.

   FileClose(handle);
   PRTF(FileGetInteger(sourceFILE_CREATE_DATE)); // 1629757115, example
   PRTF(FileGetInteger(sourceFILE_MODIFY_DATE)); // 1629757115, example

Esperemos 3 segundos antes de llamar a FileCopy. Esto le permitirá ver la diferencia en las propiedades del archivo original y su copia. Esta pausa no tiene nada que ver con el bloqueo previo del archivo: podríamos copiar inmediatamente después de cerrar el archivo, o incluso mientras lo escribimos si la opción FILE_SHARE_READ estaba activada.

   Sleep(3000);

Copiemos el archivo. Esta vez la operación tiene éxito. Veamos las propiedades de la copia.

   PRTF(FileCopy(source0destinationFILE_COMMON)); // true
   PRTF(FileGetInteger(destinationFILE_CREATE_DATEtrue)); // 1629757118, +3 seconds
   PRTF(FileGetInteger(destinationFILE_MODIFY_DATEtrue)); // 1629757115, example

Cada archivo tiene su propio tiempo de creación (para una copia es tres segundos más tarde que para el original), pero el tiempo de modificación es el mismo (la copia ha heredado las propiedades del original).

Ahora vamos a intentar mover la copia de nuevo a la carpeta local. No se puede hacer sin la opción FILE_REWRITE porque no hay permiso para sobrescribir el archivo original.

   PRTF(FileMove(destinationFILE_COMMONsource0)); // false / FILE_CANNOT_REWRITE(5020)

Cambiando el valor del parámetro conseguiremos que la transferencia de archivos se realice correctamente.

   PRTF(FileMove(destinationFILE_COMMONsourceFILE_REWRITE)); // true

Por último, también se elimina el archivo original para dejar un entorno limpio para nuevos experimentos con este script.

   ...
   FileDelete(source);
}