[Решено] EOSError 1410 при работе с TFileStream.Create

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

[Решено] EOSError 1410 при работе с TFileStream.Create

Сообщение Risto » 10.03.2016 04:33:33

UPD: Опытным путём выяснил, что вылет вообще не зависит от содержимого блока exception. Более того, точка останова в одной из подключаемых библиотек.

Идея была такая, что программа читает файл конфига в директории с экзешником, а если его нет - создаёт. На деле, если файл есть, программа читает конфиг, а если нет - идёт к except и... вылетает с исключением EOSError 1410: Class Already Exists на первой же строчке. Добавил в начало except FStream.Free - теперь вылетает на нём. Его надо как-то по-другому освобождать, или дело вообще не в TFileStream?

Код: Выделить всё
constructor HomerConf.Read;
var
  FStream: TFileStream;
  JParser: TJSONParser;
  JData: TJSONData;
  JObject: TJSONObject;
  i, n: integer;

begin
  try
    try
      FStream:=TFileStream.Create('config.json',fmOpenRead);
      try
        try
          JParser:=TJSONParser.Create(FStream);
          try
            JData:=JParser.Parse;
            JObject := TJSONObject(JData);
            GamePath := JObject.Get('GamePath');
            UserPath := JObject.Get('UserPath');
            NumActiveMods := JData.FindPath('ActiveMods').Count;
            SetLength(ActiveMods, NumActiveMods);
            for i := 0 to NumActiveMods-1 do
              ActiveMods[i] := JData.FindPath('ActiveMods['+IntToStr(i)+']').AsString;
            n := JData.FindPath('Mods').Count;
            SetLength(Mods, n);
            for i := 0 to n-1 do
              Mods[i] := JData.FindPath('Mods['+IntToStr(i)+']').AsString;
          except
          end;
        except
        end;
      finally
        JParser.Free;
      end;
    except
      try
        FStream.Free;
        FStream:=TFileStream.Create('config.json',fmOpenWrite);
        JData := GetJSON('{}');
        JObject := TJSONObject(JData);
        GamePath := ExpandFileName('./');
        UserPath := GetEnvironmentVariable('APPDATA');
        jObject.Add('GamePath', GamePath);
        jObject.Add('UserPath', UserPath);
      except
      end;
    end;
  finally
    FStream.Free;
  end;
end;
Последний раз редактировалось Risto 10.03.2016 13:45:28, всего редактировалось 3 раз(а).
Risto
незнакомец
 
Сообщения: 9
Зарегистрирован: 10.03.2016 04:11:38

Re: EOSError 1410 при работе с TFileStream

Сообщение SSerge » 10.03.2016 05:55:37

Гм...
Не логичнее ли применить конструкцию

Код: Выделить всё
if (FileExists(FileName)) then
  if (GrantedAccessToFile(FileName)) then
     // тогда читаем
  else
    // он есть, но читать его запрещено - сваливаем
else
  // создаем новый


... чем намеренно заниматься провоцированием исключений?
ps - Не ищите вторую функцию среди готовых - имеется в виду нечто, проверяющее, есть ли у вас права на доступ к файлу. Извините, на сегодняшний день такая проверка весьма актуальна

Добавлено спустя 8 минут 26 секунд:
И не стоит расчитывать, что обработчик исключения внутри исключения сработает нормально. Какой собственно except-то вы ловите? Особенно, если задуматься, как это работает. И да, если вы вошли в except, то это совсем не значит, что после вашего кода обработка исключения завершена. Еще вообще-то надо сбросить статус исключения, насколько помнится.
SSerge
энтузиаст
 
Сообщения: 971
Зарегистрирован: 12.01.2012 05:34:14
Откуда: Барнаул

Re: EOSError 1410 при работе с TFileStream

Сообщение Risto » 10.03.2016 06:59:01

SSerge писал(а):Гм...
Не логичнее ли применить конструкцию

... чем намеренно заниматься провоцированием исключений?


Может и логично, только неправильно. Тогда я не узнаю, почему код не сработал так, как мне было нужно, как избегать этой ошибки, и когда лучше использовать/не использовать лювлю исключений. Я, собственно, использовал такой код именно для того, чтобы разобраться с новым для меня механизмом, а через if-else сделать - особых знаний и не надо.

И не стоит расчитывать, что обработчик исключения внутри исключения сработает нормально. Какой собственно except-то вы ловите? Особенно, если задуматься, как это работает.


Код: Выделить всё
        jObject.Add('UserPath', UserPath);
      except
      end;


Вы про этот except? Там должно было быть завершение программы с критической ошибкой, если создать конфиг тоже не удалось. А почему не сработает?

И да, если вы вошли в except, то это совсем не значит, что после вашего кода обработка исключения завершена. Еще вообще-то надо сбросить статус исключения, насколько помнится.

Хм, а как это сделать?

Добавлено спустя 26 минут 59 секунд:
Re: EOSError 1410 при работе с исключениями
Risto писал(а):UPD: Опытным путём выяснил, что вылет вообще не зависит от содержимого блока exception. Более того, точка останова в одной из подключаемых библиотек.


Добавлено спустя 8 минут 12 секунд:
Re: EOSError 1410 при работе с исключениями
Сейчас попробую пересобрать Лазарус без левых пакетов. Если на нём запустится - вопрос снят.

Добавлено спустя 6 минут 7 секунд:
Re: EOSError 1410 при работе с исключениями
Не-а. Только вменяемое описание ошибки пропало. Так что проблема в моём коде.
Risto
незнакомец
 
Сообщения: 9
Зарегистрирован: 10.03.2016 04:11:38

Re: EOSError 1410 при работе с исключениями

Сообщение Лекс Айрин » 10.03.2016 11:12:26

Risto писал(а):Может и логично, только неправильно.

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

А может просто попытаться вынести код проверки существования файла в отдельную процедуру/функцию? не зависящую от создаваемого объекта?

Добавлено спустя 2 минуты 37 секунд:
ах да. Для отладки проходимого пути (в сложных случаях) можно использовать добавление вывода тестовых сообщений. Пусть и муторно, но зато надежно.
Аватара пользователя
Лекс Айрин
долгожитель
 
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград

Re: EOSError 1410 при работе с исключениями

Сообщение Risto » 10.03.2016 12:36:24

А ларчик просто открывался: Лазарус не желал открывать поток к несуществующему файлу. А я, наивный, надеялся, что он его создаст. Причём тут классы так и не понял, но ситуацию исправил только переход от TFileStream.Create('config.json',fmOpenWrite) к старому доброму

Код: Выделить всё
assignfile(NewFile,'config.json');
rewrite(NewFile);
closefile(NewFile);


Хоть исключения оказались не виноваты, внял советам и вернулся к if-else.

Добавлено спустя 1 час 1 минуту 43 секунды:
Re: EOSError 1410 при работе с TFileStream.Create
Спасибо, теперь знаю как это делается:
wavebvg писал(а):
Код: Выделить всё
Stream := TFileStream.Create('world.txt', fmCreate);

Почему, интересно, в доках этого не было?
Risto
незнакомец
 
Сообщения: 9
Зарегистрирован: 10.03.2016 04:11:38


Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: Google [Bot] и гости: 229

Рейтинг@Mail.ru