FileIsEnding - вечный цикл - страница 2

 
Ilnur писал (а) >>

Я надеялся, что кто-нибудь откликнется.

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

Однако, если поменять местами куски кода чтения и перемещения файлового указателя, то скрипт работает корректно.

Попробуйте заменить

        {
          Print("Ошибка перемещения файлового указателя");
          return(-1);
        }

На

        {
          continue;
        }

И прогоните скрипт еще раз.



Из собственного опыта:

Не стОит искать ошибку там, где ее скорей всего нет. Я по молодости пытался неправильную работу своего кода (С++) спихнуть на ошибки в STL. Таки нашел одну ошибку в Boost'е, но это скорей исключение, подтверждающее правило. Кому надо, тот поймет.


А если ошибка действительно есть -- выложите полностью описанный код с полностью описанным поведением (корректным и реальным).

Вам скажут спасибо и создатели, и разработчики.

Только перед этим лучше 100 раз все перепроверить.

 

В копилку странностей файловых функций от MQL4.

//11. Функция "Дописать файл одномерного строкового массива со строковыми данными с расширением *.csv".============================================================================
int WriteFileStringArray1CSV (string& NameFile,   // Название файла.
                              string& Array[],    // Одномерный массив для записи.
                              int&    Start,      // Начальный индекс в массиве.
                              int&    Count,      // Количество элементов для чтения.
                              int&    NumberLine, // Номер строки для записи.
                              int&    Delimiter)  // Знак разделителя для csv-файлов. Пример: ';'.
 {
  string Name = NameFile + ".csv";
  string Text = "";
  int    i;
  int    ERROR;
  int    Handle = FileOpen (Name, FILE_CSV|FILE_READ|FILE_WRITE, Delimiter);
  //----
  NumberLine = MathAbs (NumberLine); // На всякий случай берём модуль числа, чтобы не завершать функцию по ошибке.
  if (Handle == -1)
   {
//    Print ("Файл ", Name, " не создан. Последняя ошибка: \"", ErrorDescription (GetLastError()), "\".");
    FileClose (Handle);
    return (-1);
   }
  else
   {
    if (FileSeek (Handle, 0, SEEK_SET) == false) // Смещаем файловый указатель в начало файла.
     {
//      Print ("Ошибка в функции \"WriteFileStringArray1CSV()\". Файловый указатель файла ", Name, " не смещён. Последняя ошибка: \"", ErrorDescription (GetLastError()), "\".");
      FileClose (Handle);
      return (-1);
     }
    if (NumberLine > 1)
     {
      for (i = 1; NumberLine != i && FileIsEnding (Handle) == false;)
       {
        FileReadString (Handle);
        if (FileIsLineEnding (Handle) == true) i++;
       }
     }
    FileSeek (Handle, 0, SEEK_CUR);
    for (i = Start; i < (Start + Count); i++)
     {
      if (i == (Start + Count - 1)) Text = Text + Array[i];
      else Text = Text + Array[i] + StringSetChar ("", 0, Delimiter);
     }
//    Alert (FileTell (Handle), "; ", Text);
    ERROR = FileWrite (Handle, Text);
//    if (ERROR == -1) Print ("Ошибка в функции \"WriteFileStringArray1CSV()\". Значение в файл ", Name, " не записано. Последняя ошибка: \"", ErrorDescription (GetLastError()), "\".");
    FileClose (Handle);
   }
  return (ERROR);
 }
Строка выделенная красным вроде, как ни чего не делает и не нужна. Однако без неё записи в файл не происходит. Хотя, ни одна функция ошибок не возвращает и файловый указатель смещён куда надо. Т.е. файл дописан.
 

Есть ещё одна непонятка. 

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

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

 

Вот ещё одна странность.

Если записывать новые более длинные строки на место старых, то тоже происходят изменения в других строках, которые не затрагиваешь перезаписью.

Т.е. перезапись без ошибок возможна только при сохранении формата.

 

Читайте тут https://www.mql5.com/ru/forum/52405

 

Действительно не работает )) Вернее работает, но неправильно ))


Вот такая конструкция работать не будет:

while( !FileIsEnding(handle) ) {
    Test = FileReadInteger(handle,LONG_VALUE);
}

Дело в том, что указатель при чтении смещается на длину чтения.

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

Чтобы все это работало, нужно использовать конструкцию:


int size=FileSize(handle);
while( size > FileTell(handle) )    {
Причина обращения: