Как можно нормально прочитать файл?

 

При работе с файлами после нормальных библиотек, которые есть для Java, например, я столкнулся с некоторыми сложностями.

Как можно нормально прочитать целую строку, если нет данных её длины?

Вот, я так понял, нужно сделать типа такого:

// Чтение runtime-данных из csv-файла. ====================================================================================================================================================
void readRuntmeData(string path,                   // Каталог, в котором находится файл
                    string file,                   // Файл, из которого читаются данные
                    string dataToRead) export {    // runtime-данные для чтения
//---
  string fileName = getName() + "_runtime" + ".csv";
  int handle = FileOpen(fileName, FILE_READ|FILE_WRITE|FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_CSV, ";", CP_UTF8);

  if (handle != INVALID_HANDLE) {
    while (!FileIsEnding(handle)) {
      Print(FileReadString(handle));
      FileClose(handle);
    }
  }
}

Открываем файл, и циклком пока не конец файла читаем строки. Других вариантов я не нашёл в документации. Но принтуется не вся строка, которую потом можно нормально распарсить, а лишь её часть до ближайшего знак разделителя. В прочем согласно документации это правильно. Но, тем не менее, если нет информации какова длина строки как мне прочитать её целиком?

 
hoz:

При работе с файлами после нормальных библиотек, которые есть для Java, например, я столкнулся с некоторыми сложностями.

Как можно нормально прочитать целую строку, если нет данных её длины?

Вот, я так понял, нужно сделать типа такого:

Открываем файл, и циклком пока не конец файла читаем строки. Других вариантов я не нашёл в документации. Но принтуется не вся строка, которую потом можно нормально распарсить, а лишь её часть до ближайшего знак разделителя. В прочем согласно документации это правильно. Но, тем не менее, если нет информации какова длина строки как мне прочитать её целиком?

вы открыли файл как CSV (FILE_CSV). При этом все ReadXXXX будет извлекать запись до разделителя.
откройте просто как текстовый и будете получать полную строку чтобы самому её парсить.
Или можно внутри приведённого вами цикла вычитывать все записи строки while(!FileIsLineEnding(handle)) Print("record="+FileReadString(handle));

тут не как Java, тут для удобства спутали кислое с мягким и разбор (частоупотребимого) CSV с низкоуровневыми файловыми операциями :-)

 
Maxim Kuznetsov:

вы открыли файл как CSV (FILE_CSV). При этом все ReadXXXX будет извлекать запись до разделителя.
откройте просто как текстовый и будете получать полную строку чтобы самому её парсить.
Или можно внутри приведённого вами цикла вычитывать все записи строки while(!FileIsLineEnding(handle)) Print("record="+FileReadString(handle));

тут не как Java, тут для удобства спутали кислое с мягким и разбор (частоупотребимого) CSV с низкоуровневыми файловыми операциями :-)

Хм. Проще читать как текст, без дополнительного цикла)) Прочёл как текст:

// Чтение runtime-данных из csv-файла. ====================================================================================================================================================
void readRuntmeData(string path,                   // Каталог, в котором находится файл
                    string file,                   // Файл, из которого читаются данные
                    string dataToRead) export {    // runtime-данные для чтения
//---
  string fileName = getName() + "_runtime" + ".csv";
  int handle = FileOpen(fileName, FILE_READ|FILE_WRITE|FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_TXT, ";", CP_UTF8);

  if (handle != INVALID_HANDLE) {
    while (!FileIsEnding(handle)) {
      Print(FileReadString(handle));
    }
    FileClose(handle);
  }
}

Файл такого образца:

33330215;2018.05.25 15:23:16;1.25738 33330219;; 3333023;2018.05.25 15:23:17;1.25741 3333024;2018.05.25 15:23:19;1.25745 3333025;2018.05.25 15:23:23;1.25749

В журнале вижу результат принта:

2018.05.27 11:44:59.352 testMethod (EURUSD,D1) 3333021;2018.05.25 15:23:16;1.25738

Конца то файла нет, а принтуется только 1 строка верхняя. Что не так-то?
 
hoz:

Хм. Проще читать как текст, без дополнительного цикла)) Прочёл как текст:

Файл такого образца:

33330215;2018.05.25 15:23:16;1.25738 33330219;; 3333023;2018.05.25 15:23:17;1.25741 3333024;2018.05.25 15:23:19;1.25745 3333025;2018.05.25 15:23:23;1.25749

В журнале вижу результат принта:

Конца то файла нет, а принтуется только 1 строка верхняя. Что не так-то?

Что значит "нет конца файла" ?

если в файл всё ещё кто-то что-то пишет, это не значит что функции MQL будут его ожидать. Добежали до текущего конца файла (дальше данных пока нет) получили FileIsEnding.

Используя хитрое сочетание FILE_READ|FILE_WRITE ещё стоит передвинуть указатель в самое начало :-) см. FileSeek

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

Тестирование стратегий - Алгоритмический трейдинг, торговые роботы - MetaTrader 5
Тестирование стратегий - Алгоритмический трейдинг, торговые роботы - MetaTrader 5
  • www.metatrader5.com
Тестер стратегий позволяет тестировать и оптимизировать торговые стратегии (советники) перед началом использования их в реальной торговле. При тестировании советника происходит его однократная прогонка с начальными параметрами на исторических данных. При оптимизации торговая стратегия прогоняется несколько раз с различным набором параметров...
 
Maxim Kuznetsov:

Что значит "нет конца файла" ?

Ну так имеется цикл. Пока не достигнул конец файлп должна выполняться функция:

Print(FileReadString(handle))

для каждой строки. А на самом деле принтуется первая строка и всё. Дальше платформа "забивает" на то, что нужно принтовать все строки файла.


Maxim Kuznetsov:

если в файл всё ещё кто-то что-то пишет, это не значит что функции MQL будут его ожидать. Добежали до текущего конца файла (дальше данных пока нет) получили FileIsEnding.

Как это нет? Для того что бы не было ожидания есть функция FileClose(). А на самом деле здесь вариант попроще. Я не говорю о том, что может быть нужно что-то ожидать. Есть статический файл, со статически константными данными. Для тестирования функций этих строковых и файловых. Вот его содержимое:

33330215;2018.05.25 15:23:16;1.25738

33330219;;

3333023;2018.05.25 15:23:17;1.25741

3333024;2018.05.25 15:23:19;1.25745

3333025;2018.05.25 15:23:23;1.25749

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

// Чтение runtime-данных из csv-файла. ====================================================================================================================================================
void readRuntmeData(string path,                   // Каталог, в котором находится файл
                    string file,                   // Файл, из которого читаются данные
                    string dataToRead) export {    // runtime-данные для чтения
//---
  string fileName = getName() + "_runtime" + ".csv";
  int handle = FileOpen(fileName, FILE_READ|FILE_WRITE|FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_TXT, ";", CP_UTF8);

  if (handle != INVALID_HANDLE) {
    while (!FileIsEnding(handle)) {
      Print(FileReadString(handle));
    }
    FileClose(handle);
  }
}

Если представить, что у нас вообще не цикл, тогда будет так:

while (!FileIsEnding(handle)) {
  Print(FileReadString(handle));
  Print(FileReadString(handle));
}

Принтанётся уже 2 строки.

Если 3 принта напечатать, то 3.. И тд. Но это противоречит тому, что у нас есть цикл. Получается что цикл не работает так как должен. Он 1 строку принтанул, и дальше не делает попытки прочитать новую строку

У меня появилась мысль, т.к. цикл не рабочий, а точнее функция эта какая-то левая сделать в цикле while ещё один цикл:

    while (!FileIsEnding(handle)) {
      for (char row = 0; КОЛИЧЕСТВО СТРОК; row++) {
        Print(FileReadString(handle));
      }
    }

Но КОЛИЧЕСТВО СТРОК у нас не известно, поэтому такой вариант тоже не подходит.


Maxim Kuznetsov:

Используя хитрое сочетание FILE_READ|FILE_WRITE ещё стоит передвинуть указатель в самое начало :-) см. FileSeek

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

Хм. Так получается типа так нужно что-ли?

while (!FileIsEnding(handle)) {
  Print(FileReadString(handle));
  FileSeek(handle, 1, SEEK_CUR);
}

Я попробывал посредством FileSeek сместить указатель на 1 байт. Пробывал на 5 и больше. Ничего не даёт. И вообще, кто его знает где указатель находится, после вызова FileIsEnding(). В справке пример и тот не рабочий...

 
hoz:

Хм. Проще читать как текст, без дополнительного цикла)) Прочёл как текст:

Файл такого образца:

33330215;2018.05.25 15:23:16;1.25738 33330219;; 3333023;2018.05.25 15:23:17;1.25741 3333024;2018.05.25 15:23:19;1.25745 3333025;2018.05.25 15:23:23;1.25749

В журнале вижу результат принта:

Конца то файла нет, а принтуется только 1 строка верхняя. Что не так-то?

забудьте Java, учите С, он рулит...тут от него больше :-)
Читаете текст ? вот и ставьте только необходимые флаги, а не все обнаруженные в документации.
и не забудьте убедится файл действительно utf-8.

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

 int handle = FileOpen(fileName, FILE_READ|FILE_TXT, ';', CP_UTF8);

  if (handle != INVALID_HANDLE) {
    while (!FileIsEnding(handle)) {
      Print(FileReadString(handle));
    }
    FileClose(handle);
  }
 
Maxim Kuznetsov:

забудьте Java, учите С, он рулит...тут от него больше :-)
Читаете текст ? вот и ставьте только необходимые флаги, а не все обнаруженные в документации.
и не забудьте убедится файл действительно utf-8.

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

Кодировка UTF-8. Лишние флаги я поубирал, это да, лишнее..

В том то и дело, что ошибок нет. Вот я принтую всё что только можно:

void readRuntmeData(string path,                   // Каталог, в котором находится файл
                    string file,                   // Файл, из которого читаются данные
                    string dataToRead) export {    // runtime-данные для чтения
//---
  string fileName = getName() + "_runtime" + ".csv";
  int handle = FileOpen(fileName, FILE_READ|FILE_SHARE_READ|FILE_TXT, ";", CP_UTF8);

  if (handle != INVALID_HANDLE) {
    while (!FileIsEnding(handle)) {
      Print("_err = ", GetLastError());
      Print(FileReadString(handle));
      Print("err = ", GetLastError());
    }
    Print("Вышли из цикла");
    FileClose(handle);
  } else {
    Print("Файл не удалось прочитать..!");
  }
}

При открытии файла ошибок нет т.к. handle != INVALID_HANDLE. В цикле тоже ошибки нет перед и после чтения 1-ой строки. Потом сразу выход из цикла и закрытие хэндла файла. Вот в журнале это видно всё:

2018.05.27 16:23:14.429 testMethod (EURUSD,D1) _err = 0

2018.05.27 16:23:14.429 testMethod (EURUSD,D1) 3333021;2018.05.25 15:23:16;1.25738 2018.05.27 16:23:14.429 testMethod (EURUSD,D1) err = 0 2018.05.27 16:23:14.429 testMethod (EURUSD,D1) Вышли из цикла

Что тут ещё можно отловить то?

 
Maxim Kuznetsov:

забудьте Java, учите С, он рулит...тут от него больше :-) 

Тут больше, а в общем, нет))

По ходу, нужно придумать какой-то костыль т.к. не работает стандартно ничего.

 

Если нужно построчное чтение, то может разделитель сменить с ";" на "\n"?


 
TheXpert:

Если нужно построчное чтение, то может разделитель сменить с ";" на "\n"?

В мт4 тоже самое у меня, кстати, тоже работает. А в 5-ке не работает..

Кстати, в 4-ке не важно как открывать файл. Так работает:

  handle_1 = FileOpen(fileName, FILE_READ|FILE_SHARE_READ|FILE_TXT, ";", CP_UTF8);

Так тоже работает:

  handle_1 = FileOpen(fileName, FILE_READ|FILE_SHARE_READ|FILE_TXT, "\r", CP_UTF8);

Кстати, вот я видео записал. Если нужно могут уменьшить разрешение.

https://youtu.be/pmCfGnl9U80

 
у меня 5 терминал не запускается, то ли из-за обновления винды, то ли из-за обновления терминала. лень разбираться, так что с МТ5 пока не помогу
Причина обращения: