Russian Qt Forum
Ноябрь 24, 2024, 04:43 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 2 [3]   Вниз
  Печать  
Автор Тема: QDataStream + exception  (Прочитано 17657 раз)
Akon
Гость
« Ответ #30 : Март 28, 2014, 07:24 »

Цитировать
Пока одни борются с ветреными мельницами, у других все работает.
Хорошо, напишите ваш код для загрузки из QByteArray (вместо QFile) с конструктором QDataStream(const QByteArray& ba).
« Последнее редактирование: Март 28, 2014, 07:27 от Akon » Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #31 : Март 28, 2014, 07:27 »

Хорошо, напишите ваш код для загрузки из QByteArray (вместо QFile).
Код
C++ (Qt)
QByteArray data;
QBuffer buf( &data );
ExProxyDev dev( &buf );
 
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #32 : Март 28, 2014, 07:33 »

с конструктором QDataStream(const QByteArray& ba).
А зачем мне это делать?
Если пользователь использует этот конструктор, то он намерено и явно отказывается от устройства умеющего посылать исключения.
Именно этот пользователь сейчас принимает решение, через что открывать данные. Ему нужны исключения - одно устройство, нет - другое.

Еще раз. Улыбающийся
Я не считаю это полноценным решением. Это решение поднятой ТС задачи, который ищет простое решение с минимальными потерями наработок и не хочет писать полноценное решение.
« Последнее редактирование: Март 28, 2014, 08:17 от Old » Записан
Akon
Гость
« Ответ #33 : Март 28, 2014, 08:43 »

Я предельно понимаю этот вариант. В случае локального использования этого пойдет и будет оптимально с точки зрения кол-ва телодвижений (написания кода). ТС здесь предложены варианты, исходя из своей конкретики он выберет более подходящее.

Мои мысли проистекают из следующего: функции сериализации - это, как правило, паблик интерфейс. Функция принимает на вход DataStream, сконструированный каким-то внешним кодом. Сл-но, в рамках вашего решения этот внешний код также придется считать локальным, поскольку в функции сериализации будет зависимость от того, каким образом создан QDataStream. Как вариант, можно проверять тип девайса из QDataStream в функции сериализации, но это, полагаю, будет совсем некрасиво.
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #34 : Март 28, 2014, 09:08 »

Мои мысли проистекают из следующего: функции сериализации - это, как правило, паблик интерфейс. Функция принимает на вход DataStream, сконструированный каким-то внешним кодом. Сл-но, в рамках вашего решения этот внешний код также придется считать локальным, поскольку в функции сериализации будет зависимость от того, каким образом создан QDataStream. Как вариант, можно проверять тип девайса из QDataStream в функции сериализации, но это, полагаю, будет совсем некрасиво.
А для чего функциям сериализации знать в какое устройство они сериализуются?
Код
C++ (Qt)
QDataStream &operator>>( QDataStream &s, MyObject &obj )
{
   s >> obj.data1 >> obj.data2 >> obj.data3;
}
 
Вот типичная функция чтения. С обычным устройством, мы сможем определить ошибку чтения (в лучшем случае) после отработки этого оператора, проверив состояние. В случае с исключениями, мы получим исключение при первой невозможности чтения данных.

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

Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #35 : Март 28, 2014, 09:30 »

Код
C++ (Qt)
QByteArray data;
QBuffer buf( &data );
ExProxyDev dev( &buf );
 
Только ExProxyBufferDev, ExProxyFileDev и.т.д. Да, так можно, о чем упоминалось в начале темы, и этот вариант выглядит самым четким. Но не одно прокси на всех  Улыбающийся

Еще одно соображение - если QDataStream заменяется наследником, то с его device() не все гладко, если клиент обратится к нему (а он может) то все, хана.

Если  вы хотите сохранить QDataStream в интерфейсе функций сериализации, .
Конечно хочу, зачем мне жесткая зависимость от самопального класса

ТС здесь предложены варианты, исходя из своей конкретики он выберет более подходящее.
Когда мне будет "очень надо" - что-то обсуждать уже времени не будет. Пока мне интересно как это сделать.
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #36 : Март 28, 2014, 09:34 »

Только ExProxyBufferDev, ExProxyFileDev и.т.д. Да, так можно, о чем упоминалось в начале темы, и этот вариант выглядит самым четким. Но не одно прокси на всех  Улыбающийся
Для чего? QBuffer это наследник QIODevice, такой же как и QFile и спокойно может проксироваться одним устройством.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #37 : Март 28, 2014, 09:37 »

Для чего? QBuffer это наследник QIODevice, такой же как и QFile и спокойно может проксироваться одним устройством.
Нет, в чем Вы можете легко убедиться сами  Улыбающийся
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #38 : Март 28, 2014, 09:38 »

Еще одно соображение - если QDataStream заменяется наследником, то с его device() не все гладко, если клиент обратится к нему (а он может) то все, хана.
С чего это? Улыбающийся
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #39 : Март 28, 2014, 09:45 »

Нет, в чем Вы можете легко убедиться сами  Улыбающийся
Убеждаюсь. У меня все работает. Улыбающийся

Код
C++ (Qt)
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
 
qint8 a = 0, b = 0, c = 0, d = 0, e = 0, f = 0;
 
try
{
QFile file( "test.dat" );
if( !file.open( QIODevice::ReadOnly ) )
{
qWarning() << "File not found.";
return 2;
}
QByteArray data = file.readAll();
 
QBuffer buf( &data );
ExProxyDev dev( buf );
dev.open( QIODevice::ReadOnly );
 
QDataStream in( &dev );
in >> a >> b >> c >> d >> e >> f;
qDebug() << in.status();
}
catch( std::exception &ex )
{
qDebug() << ex.what();
}
 
qDebug() << a << b << c << d << e << f;
 
return 0;
}
 
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #40 : Март 28, 2014, 16:13 »

А неплохая штука получается. Улыбающийся

Имеем какой то интерфейс загрузки сложного объекта:
Код
C++ (Qt)
QDataStream &operator>>( QDataStream &s, ObjA &a )
{
   s >> a.m_intVal >> a.m_strVal;
   return s;
}
 
QDataStream &operator>>( QDataStream &s, ObjB &b )
{
   s >> b.m_shortVal >> b.m_listVal;
   return s;
}
 
QDataStream &operator>>( QDataStream &s, ObjBig &big )
{
   s >> big.m_objA >> big.m_objB;
   return s;
}
 
QDataStream &operator>>( QDataStream &s, ObjSuper &super )
{
   s >> super.m_big1 >> super.m_big2 >> super.m_big3;
   return s;
}
 

Теперь, мы может загружать его по старинке:
Код
C++ (Qt)
{
   QList<ObjSuper> objs;
 
   QFile source( ... );
   if( !source.open( ... ) )
   {
         ...
   }
 
   QDataStream s( &source );
   for( int i = 0; i < 100500; ++i )
   {
       ObjSuper tmp;
       s >> tmp;
       if( s.status() )
       {
             // ААаааааа. Ошибка чтения
       }
       objs.append( tmp );
   }
}
 

А можем с исключениями:
Код
C++ (Qt)
{
   QList<ObjSuper> objs;
 
   try
   {
       QFile file( ... );
       ExProxyDev source( file );
       source.open( ... );
 
       QDataStream s( &source );
       for( int i = 0; i < 100500; ++i )
       {
           ObjSuper tmp;
           s >> tmp;
           objs.append( tmp );
       }
   }
   catch( FileError &err )
   {
        qDebug() << err.info();
   }
}
 

* Функции сериализации остаются такими же как и были. Можно сериализовать все Qt-объекты, которые могут работать с QDataStream.
* Чтение/запись завершаются сразу после получения ошибки, а не когда мы доберемся до очередной проверки и решим остановиться (+ можно контролировать точную позицию в файле).
* Минимальные изменения исходников. Меняется, только верхняя функция создающая устройство и проверяющее результат.
* Работать можно с любыми источниками QIODevice.
* Ну и весь функционал в одном классе ExProxyDev.
« Последнее редактирование: Март 28, 2014, 16:39 от Old » Записан
Страниц: 1 2 [3]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.374 секунд. Запросов: 23.