Файловый указатель - страница 3

 
Mihail Marchukajtes:

Я Вам настоятельно рекомендую не использовать разные неэффективные и костыльные решения. Если даже у Вас мало опыта в программировании, повозитесь в отладчике с файловыми операциями, изучите FileSeek(), Вам это даст нужный ценный опыт. Просто с самого начала надо идти правильным путём, пусть неумело и с ошибками. Научитесь со временем (достаточно быстро).

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

Если с целью визуального анализа или для импорта в эксель, тогда уж нужен текстовый или csv, хотя и будет менее эффективно. Но тогда зачем нужен прямой доступ к конкретной строке? Обычно при сборе данных просто дописывают в конец. Как я писал, для перемещения назад надо просто в цикле i=[0...-N] устанавливать FileSeek(h, i, SEEK_END) и проверять байт на '\n' и '\r'. 

Для бинарного файла ещё проще - от конца файла возвращаемся на нужное фиксированное число байт (размер записи) - FileSeek(h, -size, SEEK_END). Это и будет начало последней записи. И так можно перемещаться назад.

Документация по MQL5: Константы, перечисления и структуры / Константы ввода/вывода / Позиционирование внутри файла
Документация по MQL5: Константы, перечисления и структуры / Константы ввода/вывода / Позиционирование внутри файла
  • www.mql5.com
Большая часть файловых функций связана с операциями чтения/записи информации. При этом с помощью функции FileSeek() можно указывать положение файлового указателя на позицию внутри файла, с которой будет...
 
Edgar Akhmadeev:

Я Вам настоятельно рекомендую не использовать разные неэффективные и костыльные решения. Если даже у Вас мало опыта в программировании, повозитесь в отладчике с файловыми операциями, изучите FileSeek(), Вам это даст нужный ценный опыт. Просто с самого начала надо идти правильным путём, пусть неумело и с ошибками. Научитесь со временем (достаточно быстро).

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

Если с целью визуального анализа или для импорта в эксель, тогда уж нужен текстовый или csv, хотя и будет менее эффективно. Но тогда зачем нужен прямой доступ к конкретной строке? Обычно при сборе данных просто дописывают в конец. Как я писал, для перемещения назад надо просто в цикле i=[0...-N] устанавливать FileSeek(h, i, SEEK_END) и проверять байт на '\n' и '\r'. 

Для бинарного файла ещё проще - от конца файла возвращаемся на нужное фиксированное число байт (размер записи) - FileSeek(h, -size, SEEK_END). Это и будет начало последней записи. И так можно перемещаться назад.


даже и сказать нечего....просто facepalm

 
Maxim Kuznetsov:

даже и сказать нечего....просто facepalm

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

 
Maxim Kuznetsov:


даже и сказать нечего....просто facepalm

От Вас вроде и не ждали.

А Вы хотели, чтобы я полностью расписал код? 

UPD: Я так и не понял, что Вас так шокировало, уж напишите, не побрезгуйте убогим. Но ок, вот максимально упрощённый код. Чтобы не переоткрывать файл с бинарного на текстовый и обратно, как я писал ранее, пусть будет менее эффективное чтение строки вместо байта, и сравнение с 0 вместо '\n' и '\r'.

void 
OnStart() {
        int h = FileOpen("/RevertTest/EURUSD.m.set", FILE_READ|FILE_TXT|FILE_ANSI|FILE_COMMON);
        int i;

        for (i = -3; ; --i) {
                FileSeek(h, i, SEEK_END);
                string s = FileReadString(h, 1);
                uchar c = StringGetCharacter(s, 0);
                if (c == 0) {
                        //++i;          // Скорректируем указатель, если надо запомнить
                        break;
                }
        }

        Print(FileReadString(h));       // Убеждаемся, что стояли на последней строке
}

Единственное, в чём ошибся: i надо начинать не с 0, упустил что файл завершается переводом строки. Не думаю, что эта мелочь заставила Вас стыдиться за меня.

Сам бы я так не делал. Надо использовать бинарный файл.
 

Решил проблему побайтного чтения(надо было последнюю строку получать) так:


//блок чтения последней строчки из файла
//открывать так: int file_handle=FileOpen(SymbolInfoString(_Symbol,SYMBOL_BASIS)+".csv",FILE_READ|FILE_WRITE|FILE_TXT); 
// режим txt использовал, чтобы FileReadString читала всю строчку, а не до разделителя
       string string_from_file = FileReadString(file_handle);
      FileSeek(file_handle,-100,SEEK_END); //отступ в 100 байт от конца файла. У меня нефиксированная длина строчек, но столько точно должно хватить
     
      while(!FileIsEnding(file_handle))  
      { 
      string scum = FileReadString(file_handle);
      
      if(scum=="") break;  //последняя строчка файла в этом примере пустая
      else string_from_file=scum;
      
      }
      Print(string_from_file);
      //конец блока
Причина обращения: