Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Чтение двоичных файлов
Форум на CrossPlatform.RU > Библиотеки > Qt > Qt Ввод/Вывод, Сеть. Межпроцессное взаимодействие
AD
Ну задачка в принципе уже решена, но это сделано с помощью WinApi функций, таких как
::ReadFile()
А теперь хочу решить ее с помощью QDataStream. Подскажите, пожалуйста, как правильно скачать в свои структуры из файла! Подскажите, пожалуйста, как это в коде сделать?
Мои предположения: эту иою структуру (обзовем ее T) занести в QVector и потом сделать: QVector<T*> vecT;
QDataStream in(file);
in >> vecT;

правильная мысль? Или надо по-другому?
sploid
тогда уж так:
QVector< T > vectT;
QDataStream in(file);
in << vectT;

вектор умеет сохранять себя, для этого нужно что бы элементы вектора тоже умели себя сохранять.
в доке это написано:
http://doc.trolltech.com/4.4/qvector.html
в разделе "Related Non-Members"
AD
Помогите пожалуйста, я немного запутался.
Вот структура, которую я пытаюсь считать из файла
struct MAC4Header
{
    enum {
        SIGN_SIZE = 16,
        LIB_IDENT_SIZE = 256 - SIGN_SIZE - 2 * sizeof(int) };
    enum {
        CUR_VERSION_MAJOR = 1,
        CUR_VERSION_MINOR = 0,
         };
    char  Signature[ SIGN_SIZE ];
    char  LibraryIdent[ LIB_IDENT_SIZE ];
    int   VersionMajor;
    int   VersionMinor;

    float Latb;
    float Late;
    float Lonb;
    float Lone;

    unsigned int Year;
    unsigned int Month;
    unsigned int Day;
    unsigned int Hour;
    unsigned int Min;
    unsigned int Sec;
    unsigned int Milliseconds;

    unsigned long Crc32;

    unsigned int ChartNumber;
    unsigned int SumSize;
};


Вот так я переопределил оператор operator>>
QDataStream& operator>>(QDataStream& in, MAC4Header& lib_head)
    {
        QString libIdent;
        int _crc = 0;
        in >> libIdent;
        string libIdentificator = libIdent.toStdString();
        strcpy(lib_head.LibraryIdent, libIdentificator.c_str());
        in >> lib_head.VersionMajor >> lib_head.VersionMinor >> lib_head.Latb >> lib_head.Late >> lib_head.Lonb;
        in >> lib_head.Lone >> lib_head.Year >> lib_head.Month >> lib_head.Day >> lib_head.Hour >> lib_head.Min;
        in >> lib_head.Sec >> lib_head.Milliseconds >> lib_head.ChartNumber >> lib_head.SumSize >> _crc;
        lib_head.Crc32 = _crc;

        return in;
    }


Вот само считывание
bool LibReader::TRead()
    {
        bool ret = false;
        if(!open()) return ret;

        QDataStream in(file);
        int v = in.version();

        QVector<MAC4Header> libVec(1, MAC4Header());
        int size = libVec.size();
        in >> libVec;
        //libHeader = vecLib.front();
        
        /*QVector<MAC4Header*> libHeader(1);
        QVector<MAC4ChartHeader*> chartHeader;

        in >> libHeader;*/

        shutdown();
        return ret;
    }


Ну и на всякий случай привожу код LibReader:
/// Класс для чтения библиотек карт
    class LibReader
    {
    private:
        QFile* file;                                ///< файл для чтения библиотек карт
    public:
        LibReader(const QString fileName): file(new QFile(fileName)) {}
        ~LibReader() { delete file; }
        bool open() { if(isOpen()) shutdown(); file -> open(QIODevice::ReadOnly); return isOpen(); }
        bool isOpen() { return file -> isOpen(); }
        void setFilename(const QString fileName) { if(isOpen()) shutdown(); file -> setFileName(fileName); }
        void shutdown() { file -> close(); }
        bool exists() const { return file -> exists(); }
        bool TRead();
        bool loadCharts();
    };


А вопрос вот в чем. Он при чтении вектора выдает бешеный размер и в итоге крутится внутри этого цикла (залез дебаггером и посмотрел)!
Как считать все-таки правильно?
AD
Кто знает правильное решение, поскажите, пожалуйста?
ViGOur
А как ты записываешь вектор в файл?
AD
Цитата(ViGOur @ 9.7.2008, 11:19) *
А как ты записываешь вектор в файл?

Вообще файл уже готовый.
Простейший пример создал и то не работает. Вот код. Где ошибка, в душе не знаю:
struct _str 
{
    int y;
    QString s;
    double n;
    _str(): y(100), s("Hello, Kelly!"), n(0.9652) {}
};
QDataStream& operator>>(QDataStream& in, _str& ls);
QDataStream& operator<<(QDataStream& out, const _str& ls);


QDataStream& operator>>(QDataStream& in, _str& ls)
{
    in >> ls.y >> ls.s >> ls.n;
    return in;
}

QDataStream& operator<<(QDataStream& out, const _str& ls)
{
    out << ls.y << ls.s << ls.n;
    return out;
}

А далее в функции делаю следующее:

QFile fl("nt.dat");
fl.open(QIODevice::WriteOnly);
_str un;
QDataStream out(&fl);
out << un;
fl.close();

un.s = "YYY";
un.n = -0.18;
un.y = 1;

QFile fl1("nt.dat");
fl1.open(QIODevice::ReadOnly);
QDataStream in(&fl);
in >> un;
fl.close();


Пишет правильно, а вот считывает ахинею!

Сделал в приведенном примере кое-какие поправки: стал записывать и считывать через вектор. Записывает он правильно, но в начале плюс ко всему пишет и размер вектора (вот поэтому у меня происходит зацикливание - нет указания на размер вектора). А вот при считывании все-равно в вектор ахинею пишет. Вот код:
_str un;
QVector<_str> unv;
unv.push_back(un);

QFile fl("nt.dat");
fl.open(QIODevice::WriteOnly);
QDataStream out(&fl);
out << unv;
fl.close();

unv[0].y = 1;
unv[0].s = "Hi";
unv[0].n = 1.3;

QFile fl1("nt.dat");
fl1.open(QIODevice::ReadOnly);
QDataStream in(&fl);
in >> unv;
fl.close();
Гость
Возможно баг.
Я вообще не могу найти реализации чтения QVector.
AD
Цитата(Гость @ 9.7.2008, 13:40) *
Возможно баг.
Я вообще не могу найти реализации чтения QVector.

C тестовым примером разобрался. А вот со своим еще нет.
Ошибка в тестовом примере была вот в этой строчке:
QDataStream in(&fl);

А надо
QDataStream in(&fl1);
ViGOur
Копи-пасте вредно для здоровья! ;)
Попробуй так:
QFile fl("nt.dat");
fl.open(QIODevice::WriteOnly);
_str un;
QDataStream out(&fl);
out << un;
fl.close();

un.s = "YYY";
un.n = -0.18;
un.y = 1;

QFile fl1("nt.dat");
fl1.open(QIODevice::ReadOnly);
QDataStream in(&fl1);
in >> un;
fl1.close();
AD
Цитата(ViGOur @ 9.7.2008, 14:05) *
Копи-пасте вредно для здоровья! ;)
Попробуй так:
QFile fl("nt.dat");
fl.open(QIODevice::WriteOnly);
_str un;
QDataStream out(&fl);
out << un;
fl.close();

un.s = "YYY";
un.n = -0.18;
un.y = 1;

QFile fl1("nt.dat");
fl1.open(QIODevice::ReadOnly);
QDataStream in(&fl1);
in >> un;
fl1.close();

Уже пробовал. Тоже работает. НО ЭТО ВСЕ В ТЕСТЕ! А вот мою библиотеку картографическую, не хочет читать!
ViGOur
Приведи оператор operator<<.
AD
Цитата(ViGOur @ 9.7.2008, 14:17) *
Приведи оператор operator<<.

Не понял. Зачем? Мне ее не надо писать, ее надо только прочесть. Или надо тут привести код оператора operator>>?
ViGOur
а кто пишет эту структуру?
как я понял не ты, правильно?

если ты читаешь настоящий nt.dat, то QDataStream тебе не подойдет для чтения, прийдется читать с помощью read и write.
что в принципе удобней. :)
AD
Цитата(ViGOur @ 9.7.2008, 14:42) *
а кто пишет эту структуру?
как я понял не ты, правильно?

если ты читаешь настоящий nt.dat, то QDataStream тебе не подойдет для чтения, прийдется читать с помощью read и write.
что в принципе удобней. :)

Скажем так, файлы nt.mac (nt.dat - был тестовый) пишутся другой программой, которую делал я (программа написана на GUI MFC). Там это реализовано с помощью WinApi - ReadFile, WriteFile!
А как правильно прочесть с помощь read()? Можно примерчик куска кода?
ViGOur
А как ты читаешь на MFC? :)

read и write работаю на подобии ReadFile и WriteFile. ;)
AD
Цитата(ViGOur @ 9.7.2008, 15:16) *
А как ты читаешь на MFC? :)

read и write работаю на подобии ReadFile и WriteFile. ;)

QDataStream, говоришь, для этого не подойдет. А что использовать? QIODevice или QFile?
ViGOur
Цитата(AD @ 9.7.2008, 15:40) *
А что использовать? QIODevice или QFile?
QFile
AD
Цитата(ViGOur @ 9.7.2008, 15:45) *
QFile

Вопрос уточню:
в ReadFile, WriteFile - есть параметры типа void*, которые можно привести к моим (пользовательским) типам.
В Qt описание read следующее:
Цитата
qint64 read ( char * data, qint64 maxSize )
Reads at most maxSize bytes from the device into data, and returns the number of bytes read. If an error occurs, such as when attempting to read from a device opened in WriteOnly mode, this function returns -1.
0 is returned when no more data is available for reading.
See also readData(), readLine(), and write().

QByteArray read ( qint64 maxSize )
This is an overloaded member function, provided for convenience.
Reads at most maxSize bytes from the device, and returns the data read as a QByteArray.
This function has no way of reporting errors; returning an empty QByteArray() can mean either that no data was currently available for reading, or that an error occurred.

Каким образом я смогу эти типы привести к нужному мне типу? А мне нужен тип MAC4Header. Выше уже приводилась его структура.
ViGOur
Вот так:
    _str strIn;
    QFile f1("nt.dat");
    f1.open(QIODevice::WriteOnly);
    f1.write( (const char *)&strIn, sizeof( strIn));
    f1.close();

    _str strOut;
    strOut.n = .0123;
    strOut.s = "test";
    strOut.y = 1;

    QFile f2("nt.dat");
    f2.open(QIODevice::ReadOnly);
    f2.read( (char *)&strOut, sizeof( strOut));
    f2.close();
void*
может проще для таких структур данных использовать XML? тем более в Qt есть и SAX-парсеры, и DOM-парсеры...
AD
Цитата(void* @ 9.7.2008, 16:19) *
может проще для таких структур данных использовать XML? тем более в Qt есть и SAX-парсеры, и DOM-парсеры...

А как именно хранить их в XML? Сам вариант решения, возможно, интересен, но мне не подойдет. Двоичный файл, который я хочу прочитать, является картографической библиотекой, которую умеют обрабатывать все наши приборы. Мне необходимо научиться читать его в таком виде.

VigOur, спасибо! Сейчас попробую! :)

P.S. Проблема решена!
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2024 IPS, Inc.