Работа с файлами. - страница 4

 

TheXpert:

ОМГ! Там где вывод вообще маразм. Вот так потом и появляются заявочки типа "ООП быстрее" или "индикаторы медленные, надо переносить весь код в советник" .

Да я понимаю что все работает не так как задумано, по крайней мере нормальное применение FileFlush() должно быть отличимо быстрей чем FileClose().

Только вот мне все рвно кажется что внутри цикла не стоит втыкать подобных вещей, в любом случае не очень сильно помогут.

Да и если я правильно понял пример для MQL4 там вызов FileFlush() расположен между двух циклов (что и натолкнуло меня на мысль о том что в цикле именно это тормозом и является).

  int bars_count=Bars;
  int handle=FileOpen("mydat.csv",FILE_CSV|FILE_WRITE);
  if(handle>0)
    {
     FileWrite(handle, "#","OPEN","CLOSE","HIGH","LOW");
     for(int i=0;i<bars_count;i++)
       FileWrite(handle, i+1,Open[i],Close[i],High[i], Low[i]);
     

FileFlush(handle);

     ...      for(int i=0;i<bars_count;i++)        FileWrite(handle, i+1,Open[i],Close[i],High[i], Low[i]);      FileClose(handle);     }

Таким образом если я правильно понимаю логику разработчиков то открывать файл нужно в OnInit / Конструкторе основного класса (возможно и не только в конструкторе), закрывать в OnDeint / Деструктивные основного класса.

Во всех остальных случаях вместо FileClose юзаем FileFlush (после FileWrite и после циклов).


 

TheXpert:

Yedelkin:

При этом поменял местами строчки, согласно документации:

         FileFlush(handle_file);
         FileWrite(handle_file,t);

Где в документации такое написано?

Есть такая фраза в Справочнике MQL5:

FileFlush

Примечание

Функцию FileFlush() необходимо вызывать между операциями чтения из файла и записи в файл.

 Если "запись в файл" == функция FileWrite(), то читаем: "Функцию FileFlush() необходимо вызывать перед функцией FileWrite()". Или у Вас иное мнение?

TheXpert:

Yedelkin:
Но смысла вызывать FileFlush() перед FileWrite() пока  не понял.
 

 Как можно понять смысл того, в чем его нет? Верните порядок строк на родину и перепроверьте. Видимо в документации не совсем правильно выразились.

Это хорошо, когда при изучении нового материала заранее знаешь, в чём есть смысл, а в чём его нет. Поскольку природа нас такими талантами не наградила, приходится "брать с боем каждую новую высоту", тестировать, интерпретировать документацию и результаты. Я даже не уверен, правильно ли написаны сами тесты. Поначалу интуитивно поставил FileFlush() после FileWrite(), но после перепрочтения Справочника тот пример удалил.

TheXpert:

Interesting:

ОМГ! Там где вывод вообще маразм. Вот так потом и появляются заявочки типа "ООП быстрее" или "индикаторы медленные, надо переносить весь код в советник" .

 Было бы замечательно, если б после каждой оценки "Ваш вывод - маразм" шло пояснение, в чём этот самый маразм заключается :) А то как-то непонятно, в каком направлении двигаться любознательным при такой строгости судейского корпуса :)

 
TheXpert:

Смысла флашить изменения до их появления нет, т.к. их еще нет :)

Не поверите, но именно по этой причине я и написал "Но смысла вызывать FileFlush() перед FileWrite() пока  не понял", сославшись перед этим на документацию. Подвергать же сомнению каждую строчку документации - наглости и знаний пока не хватает :)
...В общем, курс ясен - ждем, что скажут разработчики, если действительно обнаружена некая проблема.
 
Yedelkin:

Есть такая фраза в Справочнике MQL5:

 Если "запись в файл" == функция FileWrite(), то читаем: "Функцию FileFlush() необходимо вызывать перед функцией FileWrite()". Или у Вас иное мнение?

Давайте разберем "довольно неудач" описание и пример к этой функции для MQL4.

void FileFlush( int handle)


Сброс на диск всех данных, оставшихся в файловом буфере ввода-вывода.

Замечания: функцию FileFlush() необходимо вызывать между операциями чтения из файла и записи в файл.
При закрытии файла данные сбрасываются на диск автоматически, поэтому нет необходимости вызывать функцию FileFlush() перед вызовом функции FileClose().

Выделенная тут строка приводится Вами в качестве аргументации необходимости ставить в цикле вызов FileFlush перед записью в файл.

Но если понимать данное замечание дословно мы получим следующее:

функцию FileFlush() необходимо вызывать между операциями чтения из файла (а чтение это как известно FileReadXXX) и записи в файл (с записью связаны FileWrite и FileWriteXXX).

При закрытии файла (читаем  - при выполнении FileClose) данные сбрасываются на диск автоматически (читаем - выполнение FileFlush производится автоматически).


На мой взгляд разработчики не сильно заботились о правильности чтения справки даже в варианте для MQL4, про перенос урезанной части в MQL5 вообще говорить смешно.

Как минимум второе предложение в приведенном тут замечании на мой взгляд должна выглядеть следующим образом:

Перед закрытии файла данные сбрасываются на диск автоматически, поэтому нет необходимости вызывать функцию FileFlush() перед вызовом функции FileClose().

Это тоже немного коряво, но с определенной точки зрения более доходчиво объясняет почему не следует использовать FileFlush перед закрыитием файла при помощи FileClose.


С примером тоже не все так просто, в тексте пишется про одно (использование между операциями чтения и записи), а пример опиысвает применение между двумя циклами записи (работа в нутри циклов кстати вообще не рассматрвивается в справке).

Таким образом как минимум нужно добавить следующее:

1. Описание того что такое этот самый буфер ввода-вывода и что на самом деле происходит в нем между открытием файла, чтением блока данных, записью блока данных и закрытием файла.

Скорей всего это касается всего раздела про файловые операции.

2. Привести нормально понимаемый пример (можно на основе класса) того как правильно использовать вызов FileFlush при одиночном обращении к файлу (к примеру запись значения по таймеру).

3 Привести нормальный пример вызова при работе с массивов. насколько я понимаю тот пример что описан в спрвке по MQL4 относился к работе с большими массивами, но при этом неправильно это иллюстрировал (одним словом - зачем два раза записывать довольно большой объем одинаковых данных в файл если это можно сделать за несколько раз?).

FileFlush - Документация на MQL4
  • docs.mql4.com
FileFlush - Документация на MQL4
 
Interesting:

Выделенная тут строка приводится Вами в качестве аргументации необходимости ставить в цикле вызов FileFlush перед записью в файл.

Но если понимать данное замечание дословно мы получим следующее:

функцию FileFlush() необходимо вызывать между операциями чтения из файла (а чтение это как известно FileReadXXX) и записи в файл (с записью связаны FileWrite и FileWriteXXX).

При закрытии файла (читаем  - при выполнении FileClose) данные сбрасываются на диск автоматически (читаем - выполнение FileFlush производится автоматически).

Ход мысли понял. Каюсь, что по незнанию приравнял операцию "чтение из файла" к функции FileOpen() (у меня эксперт будет читать только из OnInit(), при обработке же тиков и пользовательских событий - только записывать; именно по этой причине функции типа FileReadXXX() в цикле не рассматривал). Тем не менее, FileFlush() перед FileWriteXXX() - принцип в обоих справочниках указан один и тот же. ..Да и не аргументация это была в её классическом понимании (как обоснование своей позиции), а просто ответ на вопрос, с какого перепугу я написал ту фразу.

В общем, если разработчики здесь не ответят, вечером напишу заявку со ссылкой на обсуждение и промежуточные результаты. Даже две нужны заявки: 1) "баг - не баг" и 2) изменения в документации. Вторую заявку не желаете сами оформить, раз уж так глубоко копнули тему? 

 
Yedelkin:

Ход мысли понял. Каюсь, что по незнанию приравнял операцию "чтение из файла" к функции FileOpen() (у меня эксперт будет читать только из OnInit(), при обработке же тиков и пользовательских событий - только записывать; именно по этой причине функции типа FileReadXXX() в цикле не рассматривал). Тем не менее, FileFlush() перед FileWriteXXX() - принцип в обоих справочниках указан один и тот же. ..Да и не аргументация это была в её классическом понимании (как обоснование своей позиции), а просто ответ на вопрос, с какого перепугу я написал ту фразу.

В общем, если разработчики здесь не ответят, вечером напишу заявку со ссылкой на обсуждение и промежуточные результаты. Даже две нужны заявки: 1) "баг - не баг" и 2) изменения в документации. Вторую заявку не желаете сами оформить, раз уж так глубоко копнули тему? 

1. Да это разве глубока? Я бы может с радостью и наспиал, если понимал что разработчики хотят сказать и где.

А то вот так иногда выходит: упоминание о буфере ввода-вывода есть, а нормального описания по нему нет. Или тут каждый знает что такое ФАЙЛОВЫЙ БУФЕР ВВОДА-ВЫВОДА?

Неужели трудно добавить нормальное описание данного вопроса в главу про файловые операции? Или теперь весь нет гуглить в поисках ответа что и как задумывали разработчики?

Я понимаю что размер справки ограничен, но зачем же так издеваться над теми кто только начинает изучать MQL?

2. Почему хоть какое-то упоминание об этом самом буфере я нарыл только в справке по данной функции, почему об этом не говориться в других местах раздела посвященного файловым операциям?

3. предположим я имею некое представление об этом самом буфере ввода-вывода примерно в таком виде

С файловой системой связано понятие  буфера  ввода-вывода. Ввод  и вывод данных осуществляется через этот буфер.

Буфер - это область в памяти,  которая выделяется для каждого файла.

При записи в файл вся  информация сначала направляется в буфер и там накапливается до тех пор,  пока весь объем буфера не будет заполнен.  Только  после этого или после специальной команды сброса (к примеру FileClose или FileFlush) происходит передача данных из буфера в файл.

При чтении из файла данные вначале считываются в буфер, причем данных считывается не столько, сколько запрашивается,а сколько поместится в буфер.

И разработчики всерьез полагают что это вся информация которая может интересовать новичка начавшего изучать MQL (если конечно такое определение можно считать справедливым для данного языка)?

Вот к примеру и мне интересно стало получить ответ на вопрос - А каков размер этого самого буфера и как он определяется?

На мой взгяд вся эта информация, и не только эта должна быть в документации по языку (именно там, а не в различных статьях и обсуждениях на форуме).

 
Interesting:
ОК, попробую сам написать-сослаться
 

Почему скрипт не возвращает фактическую "Дату последнего чтения" файла?

int handle_file;
void OnStart()
  {
   handle_file=FileOpen("Ye_file2.bin",FILE_READ|FILE_WRITE|FILE_BIN);
   switch(handle_file)
     {
      case  INVALID_HANDLE: break;
      default:
         Print("Дата создания файла Ye_file2.bin: ",(datetime)FileGetInteger(handle_file,FILE_CREATE_DATE));
         for(int i=0;i<3;i++)
           {
            Sleep(3000);
            FileReadInteger(handle_file,CHAR_VALUE);
            Print("Дата последнего чтения Ye_file2.bin: ",(datetime)FileGetInteger(handle_file,FILE_ACCESS_DATE));
           }
         FileClose(handle_file);
     }
  }
 
Yedelkin:

Почему скрипт не возвращает фактическую "Дату последнего чтения" файла?

Последнего доступа а не чтения. Переоткройте хэндл и будет вам щасте.
 
TheXpert:
Последнего доступа а не чтения.

ОК, как Вы могли заметить, в своём вопросе я дословно вопроизвёл фразу из документации:

ENUM_FILE_PROPERTY_INTEGER

Идентификатор

Описание идентификатора

FILE_EXISTS

Проверка на существование

FILE_CREATE_DATE

Дата создания

FILE_MODIFY_DATE

Дата последнего изменения

FILE_ACCESS_DATE

Дата последнего чтения

Вопрос 1: Вы считаете, что в документации опечатка, и что вместо "Дата последнего чтения" должно стоять что-то типа "Дата последнего открытия"? По крайней мере, из Вашего ответа видно, что операции "чтение файла" и "доступ к файлу"  означают для Вас различные по своему смыслу операции.

Далее. Если несколько раз перезапустить приложенный ранее скрипт, то обнаружится примерно вот такое поведение:

FK      0       FileInteger (EURGBP,M1) 21:33:56        Дата создания файла Ye_file2.bin: 2011.09.03 21:22:25
IP      0       FileInteger (EURGBP,M1) 21:33:59        Дата последнего чтения Ye_file2.bin: 2011.09.03 21:33:57
RL      0       FileInteger (EURGBP,M1) 21:34:02        Дата последнего чтения Ye_file2.bin: 2011.09.03 21:33:57
NH      0       FileInteger (EURGBP,M1) 21:34:06        Дата последнего чтения Ye_file2.bin: 2011.09.03 21:33:57
MH      0       FileInteger (EURGBP,M1) 21:34:43        Дата создания файла Ye_file2.bin: 2011.09.03 21:22:25
EP      0       FileInteger (EURGBP,M1) 21:34:46        Дата последнего чтения Ye_file2.bin: 2011.09.03 21:34:06
HL      0       FileInteger (EURGBP,M1) 21:34:50        Дата последнего чтения Ye_file2.bin: 2011.09.03 21:34:06
IH      0       FileInteger (EURGBP,M1) 21:34:53        Дата последнего чтения Ye_file2.bin: 2011.09.03 21:34:06

 Т.е. при первом запуске скрипта получаем, что в 21:34:06 происходит третье по счёту обращение к функции FileReadInteger(), но в качестве даты последнего чтения/доступа указано другое время, а именно: 21:33:57. Однако при втором (через 37 секунд) запуске скрипта получаем, что первое по счёту обращение к функции FileReadInteger() выдаёт время 21:34:06, т.е. время последнего обращения к функции FileReadInteger() на предыдущем запуске скрипта.

Кроме этого, видно, что второй запуск скрипта состоялся примерно в 21:34:43,  а это значит, что в это же время произошло "переоткрытие хендла", как Вы это называете. Но после такого "переокрытия хендла" возвращается 21:34:06, т.е. совершенно не то время, о котором Вы говорите.

Вопрос 2: как это интерпретировать? 

TheXpert:
Переоткройте хэндл и будет вам щасте.

В текущей ситуации щастье ожидается, когда свойства файлов будут получены без "переоткрытия" хендла.

Причина обращения: