- Способы хранения информации: текстовый и двоичный
- Запись и чтение файлов в упрощенном режиме
- Открытие и закрытие файлов
- Управление дескрипторами файлов
- Выбор кодировки для текстового режима
- Запись и чтение массивов
- Запись и чтение структур (бинарные файлы)
- Запись и чтение переменных (бинарные файлы)
- Запись и чтение переменных (текстовые файлы)
- Управление позицией внутри файла
- Получение свойств файла
- Принудительная запись кэша на диск
- Удаление и проверка на существование файла
- Копирование и перемещение файлов
- Поиск файлов и папок
- Работа с папками
- Диалог выбора файла или папки
Копирование и перемещение файлов
Основные операции над файлами на уровне файловой системы — это копирование и перемещение. В MQL5 для этих целей реализованы две функции с одинаковыми прототипами.
bool FileCopy(const string source, int flag, const string destination, int mode)
Функция копирует исходный файл source в файл destination. Оба упомянутых параметра могут содержать исключительно имена файлов или имена вместе с предваряющими их путями (иерархиями папок) в "песочницах" MQL5. Параметры flag и mode определяют, соответственно, в какой рабочей папке ищется исходный файл и какая рабочая папка является целевой: значение 0 — это папка локального текущего экземпляра терминала (или агента тестирования, если программа запущена в тестере), а значение FILE_COMMON — общая папка для всех терминалов.
Кроме того, в параметре mode можно дополнительно указать константу FILE_REWRITE (если необходимо скомбинировать FILE_REWRITE и FILE_COMMON, это делается с помощью оператора побитового ИЛИ (|)). В отсутствие FILE_REWRITE копирование поверх существующего файла запрещено. Иными словами, если файл с путем и именем, указанным в параметре destination, уже существует, необходимо подтвердить намерение его переписать, установив FILE_REWRITE. Если этого не сделать, вызов функции завершится ошибкой.
Функция возвращает true при успешном выполнении или false в случае ошибки.
Копирование может завершится ошибкой даже при разрешении, если исходный или целевой файл заняты (открыты) другим процессом.
При копировании файлов в них обычно сохраняются метаданные файловой системы (время создания, права доступа, альтернативные потоки данных). Если необходимо выполнить "чистое" копирование только данных самого файла, можно воспользоваться последовательными вызовами FileLoad и FileSave, см. раздел Запись и чтение файлов в упрощенном режиме.
bool FileMove(const string source, int flag, const string destination, int mode)
Функция перемещает или переименовывает файл. Исходные путь и имя указываются в параметре source, а целевые — в параметре destination.
Список параметров и принцип их действия — такие же, как для функции FileCopy. Грубо говоря, функция FileMove производит ту же работу, что и FileCopy, но дополнительно удаляет исходный файл после успешного копирования.
Приемы работы с функциями изучим на практике с помощью скрипта FileCopy.mq5. В нем заведено 2 переменных с именами файлов. Оба файла не существуют на момент запуска скрипта.
const string source = "MQL5Book/source";
|
В OnStart произведем последовательность действий по простому сценарию. Для начала попробуем скопировать файл source из локального рабочего каталога в файл destination общего каталога. Мы ожидаемо получим результат false, а код ошибки в _LastError будет равен 5019 (FILE_NOT_EXIST).
void OnStart()
|
Поэтому создадим исходный файл привычным способом, запишем некие данные и сбросим на диск.
int handle = PRTF(FileOpen(source, FILE_TXT | FILE_WRITE)); // 1
|
Поскольку файл остался открытым и при открытии не было указано разрешение FILE_SHARE_READ, доступ к нему другими способами (минуя дескриптор) пока заблокирован. Поэтому следующая попытка копирования вновь завершится ошибкой.
PRTF(FileCopy(source, 0, destination, FILE_COMMON)); // false / CANNOT_OPEN_FILE(5004) |
Закроем файл и повторим попытку. Но предварительно выведем в журнал свойства получившегося файла: когда он создан и модифицирован. Оба свойства будут содержать текущую метку времени на вашем компьютере.
FileClose(handle);
|
Выждем 3 секунды прежде чем вызывать FileCopy. Это позволит увидеть разницу в свойствах исходного файла и его копии. Эта пауза никак не связана с предыдущей блокировкой файла: мы могли бы выполнять копирование сразу после того, как закрыли файл, или даже в процессе его записи, если была бы включена опция FILE_SHARE_READ.
Sleep(3000); |
Скопируем файл — на этот раз удачно — и выведем свойства со временем для копии.
PRTF(FileCopy(source, 0, destination, FILE_COMMON)); // true
|
Нетрудно заметить, что время создания у каждого файла свое (у копии оно на 3 секунды больше, чем у оригинала), а вот время модификации одинаковое (копия унаследовала свойство оригинала).
Теперь попробуем переместить копию обратно в локальную папку. Без опции FILE_REWRITE "этот номер не пройдет", потому что нет разрешения перезаписать исходный файл.
PRTF(FileMove(destination, FILE_COMMON, source, 0)); // false / FILE_CANNOT_REWRITE(5020) |
Изменив значение параметра, добьемся успешного переноса файла.
PRTF(FileMove(destination, FILE_COMMON, source, FILE_REWRITE)); // true |
В завершение исходный файл также удаляется, чтобы оставить "чистой" обстановку для повторных экспериментов с этим скриптом.
...
|