PDA

View Full Version : How to write a QList into a binary file?



Lawand
31st March 2009, 05:52
How can I write a QList into a binary file since the QDataStream.operator<<() and QDataStream.operator>>() have no corresponding overload in which I can pass in a QList.

In the application I am writing, there is a Patient class which I have a QList of and I want to read it from a binary file at startup and manipulate it throughout the execution, then at the end, write it back into the same file.

Any advice?

spirit
31st March 2009, 07:19
it depends which type you use in template.

Lawand
31st March 2009, 15:22
Thanks for replying, the QList is of type Patient which is a class I defined, and I am getting an error when trying to write the list to a binary file, here is some code:


class Patient
{
public:
Patient();
private:
QString firstName;
QString lastName;
};

int main()
{
QList<Patient> patientList;
QFile qFile("Patient_List.bin");
if (qFile.open(QIODevice::ReadOnly))
{
QDataStream in(&qFile);
in >> patientList; //error here
}
}

spirit
31st March 2009, 15:30
implement your own QDataStrem:: operator << & >> for this type and everything should work.

Lawand
31st March 2009, 16:54
You mean something like this:

QDataStream& QDataStream::operator>>(Patient patient)
{
*this >> patient.firstName;
*this >> patient.lastName;

return *this;
}

QDataStream& QDataStream::operator<<(Patient patient)
{
*this << patient.firstName;
*this << patient.lastName;

return *this;
}

spirit
31st March 2009, 16:57
almost, I would use these signatures. :)


QDataStream &operator<<(QDataStream &in, const Patient &patient)
{
...
}

QDataStream &operator>>(QDataStream &in, Patient &patient)
{
...
}

Lawand
31st March 2009, 17:05
Please bear with me :),
I defined those in the patient.cpp file:

QDataStream& QDataStream::operator<<(QDataStream &in, const Patient &patient)
{
in << patient.firstName;
in << patient.lastName;

return in;
}

QDataStream& QDataStream::operator>>(QDataStream &out, Patient &patient)
{
out >> patient.firstName;
out >> patient.lastName;

return out;
}

but I got these errors at the opening curly brace of operator<<:

Multiple markers at this line
- non-inline function 'QDataStream& QDataStream::operator<<(QDataStream&, const
Patient&)' is defined after prior declaration as dllimport: attribute ignored
- prototype for `QDataStream& QDataStream::operator<<(QDataStream&, const Patient&)'
does not match any in class `QDataStream'
- `QDataStream& QDataStream::operator<<(QDataStream&, const Patient&)' must take
exactly one argument

and these errors at the opening curly brace of operator>>:

Multiple markers at this line
- `QDataStream& QDataStream::operator>>(QDataStream&, Patient&)' must take
exactly one argument
- prototype for `QDataStream& QDataStream::operator>>(QDataStream&, Patient&)'
does not match any in class `QDataStream'
what's wrong? :(

JhonJames
31st March 2009, 17:33
Here:



//spirit's code:
QDataStream &operator<<(QDataStream &in, const Patient &patient)


//Your code:
QDataStream& QDataStream::operator<<(QDataStream &in, const Patient &patient)
^^^^^^^^^^^^^

spirit
31st March 2009, 17:34
try this example
h - file


class Foo
{
public:
Foo(int number = 0, const QString &name = QString())
: m_number(number), m_name(name)
{}

void setNumber(int number) { m_number = number; }
int number() const { return m_number; }

void setName(const QString &name) { m_name = name; }
QString name() const { return m_name; }

private:
int m_number;
QString m_name;
};

QDataStream &operator<<(QDataStream &out, const Foo &foo);
QDataStream &operator>>(QDataStream &in, Foo &foo);


cpp-file


QFile file("test.txt");
if (!file.open(QIODevice::WriteOnly))
return;

QDataStream out(&file);
QList<Foo> res;
for (int i = 0; i < 11; ++i) {
Foo f(i, tr("name%1").arg(i));
res << f;
}
out << res;
file.close();

if (!file.open(QIODevice::ReadOnly))
return;

QDataStream in(&file);
res.clear();
in >> res;

for (int i = 0; i < res.size(); ++i) {
const Foo f = res.at(i);
qDebug() << f.number() << " " << f.name();
}

Lawand
31st March 2009, 18:32
Thank you JhonJames and spirit, writing and reading the List are working!

eekhoorn12
12th June 2009, 22:01
I have a similar kind of problem. I want to write a QList with custom classes to a binary file.

I want to write a
static QList<Server> serversList; to a binary file

I my server.cpp i have the following lines of code:

QDataStream& operator<<(QDataStream& out, const Server& server)
{
out << server.serverAddres;
...
out << server.serverUseSsl;
return out;
}

QDataStream& operator>>(QDataStream& in,Server& server)
{
in >> server.serverAddres;
...
in >> server.serverUseSsl;
return in;
}


In the file serverlist.cpp i do the operation:


if(!serverDataFile.open(QIODevice::ReadWrite))
{
return;
}

outputStream = new QDataStream(&serverDataFile);
outputStream << listofServers;


but when i compile i get the following error;


O:/projects/Post_Program/serverlist.cpp:44: error: no match for 'operator<<' in '((serverList*)this)->serverList::outputStream << serverList::listofServers'

Lawand
13th June 2009, 00:27
I think outputStream should be a QDataStream instead of QDataStream* for your code to work...

Or (if it has to be a QDataStream*) you gotta find another to call operator<<() such as:

(*outputStream) << listofServers

eekhoorn12
13th June 2009, 12:12
Thanks that solved the problem but created a new one.
I now get the following error:


f:/Qt/2009.02/qt/include/QtCore/../../src/corelib/io/qdatastream.h: In function 'QDataStream& operator<<(QDataStream&, const QList<T>&) [with T = Server]':
serverlist.cpp:45: instantiated from here
f:/Qt/2009.02/qt/include/QtCore/../../src/corelib/io/qdatastream.h:252: error: no match for 'operator<<' in 's << (+l)->QList<T>::at [with T = Server](i)'

Lawand
13th June 2009, 15:20
What are the types of server.serverAddres and server.serverUseSsl? because you might have to overload operator<<() and operator>>() on them...
As the Assistant puts it:

The QDataStream class implements the serialization of C++'s basic data types, like char, short, int, char *, etc. Serialization of more complex data is accomplished by breaking up the data into primitive units.

eekhoorn12
13th June 2009, 20:00
Server consits of a few QString's some bool's and qint32.

Lawand
13th June 2009, 22:33
Would you post the full code of the serverlist.cpp file

eekhoorn12
14th June 2009, 00:35
This is the serverlist.cpp:


#include <QDir>
#include <QMessageBox>

#include "serverlist.h"

QList<Server> listofServers;


serverList::serverList()
{
settings = new Settings();
QFile serverDataFile(settings->getappDataDir() + QDir::separator() + "servers" + QDir::separator() + "servers.dat");
serverDataFileInfo = new QFileInfo(serverDataFile);
QDataStream outputStream(&serverDataFile);
QDataStream inputStream(&serverDataFile);
}

void serverList::saveServers()
{
if(serverDataFileInfo->exists())
{
QDir newFile(serverDataFileInfo->absoluteFilePath());
newFile.mkpath(serverDataFileInfo->absolutePath());
}
if(!serverDataFile.open(QIODevice::ReadWrite))
{
QMessageBox::critical( 0, "Post program","There was a problem reading the server settings file" );
}
outputStream << listofServers;
}

void serverList::addServer(Server newServer)
{
}


This is the serverlist.h:


#ifndef SERVERLIST_H
#define SERVERLIST_H

#include <QList>
#include <QFile>
#include <QFileInfo>
#include <QDataStream>

#include <server.h>
#include <settings.h>

class serverList
{
public:
serverList();
void saveServers();
void addServer(Server newServer);
void loadServers();

private:
static QList<Server> listofServers;
Settings *settings;
QFileInfo *serverDataFileInfo;
QFile serverDataFile;
QDataStream outputStream;
QDataStream inputStream;
};

#endif // SERVERLIST_H


I will post the Server class also to get the complete picture
server.cpp:


#include "server.h"
//#include <QDataStream>

Server::Server()
{
}

void Server::setAddres(QString newAddres)
{
serverAddres = newAddres;
}

void Server::setNickname(QString newNickname)
{
serverNickname = newNickname;
}

void Server::setPort(qint32 newPort)
{
serverPort = newPort;
}

void Server::setConnections(qint32 newConnections)
{
serverConnections = newConnections;
}

void Server::setUsername(QString newUsername)
{
serverUsername = newUsername;
}

void Server::setPassword(QString newPassword)
{
serverPassword = newPassword;
}

void Server::setRequireLogin(bool newRequireLogin)
{
serverRequireLogin = newRequireLogin;
}

void Server::setUseSsl(bool newUseSsl)
{
serverUseSsl = newUseSsl;
}

QString Server::getAddres()
{
return serverAddres;
}

QString Server::getNickname()
{
return serverNickname;
}

qint32 Server::getPort()
{
return serverPort;
}

qint32 Server::getConnections()
{
return serverConnections;
}

QString Server::getUsername()
{
return serverUsername;
}

QString Server::getPassword()
{
return serverPassword;
}

bool Server::getRequireLogin()
{
return serverRequireLogin;
}

bool Server::getUseSsl()
{
return serverUseSsl;
}



QDataStream& operator<<(QDataStream& out, const Server& server)
{
out << server.serverAddres;
out << server.serverNickname;
out << server.serverPort;
out << server.serverConnections;
out << server.serverUsername;
out << server.serverPassword;
out << server.serverRequireLogin;
out << server.serverUseSsl;
return out;
}
QDataStream& operator>>(QDataStream& in,Server& server)
{
in >> server.serverAddres;
in >> server.serverNickname;
in >> server.serverPort;
in >> server.serverConnections;
in >> server.serverUsername;
in >> server.serverPassword;
in >> server.serverRequireLogin;
in >> server.serverUseSsl;
return in;
}


server.h


#ifndef SERVER_H
#define SERVER_H

#include <QString>
#include <QtGlobal>


class Server
{
public:
Server();

//Set functions
void setAddres(QString newAddres);
void setNickname(QString newNickname);
void setPort(qint32 newPort);
void setConnections(qint32 newConnections);
void setUsername(QString newUsername);
void setPassword(QString newPassword);
void setRequireLogin(bool newRequireLogin);
void setUseSsl(bool newUseSsl);

//Get functions
QString getAddres();
QString getNickname();
qint32 getPort();
qint32 getConnections();
QString getUsername();
QString getPassword();
bool getRequireLogin();
bool getUseSsl();

private:
QString serverAddres;
QString serverNickname;
qint32 serverPort;
qint32 serverConnections;
QString serverUsername;
QString serverPassword;
bool serverRequireLogin;
bool serverUseSsl;
};
#endif // SERVER_H

Lawand
14th June 2009, 12:08
In my case, I declared the functions operator<<() and operator>>() in the .h file and implemented them in the .cpp file, and when I tried removing the declarations from the .h file I got the very same error you got.

So, put those 2 lines in the server.h file:

QDataStream& operator<<(QDataStream& out, const Server& server);
QDataStream& operator>>(QDataStream& in,Server& server);

eekhoorn12
14th June 2009, 16:42
Thanks that worked. Now i have to look at my implementation of the reading of a file because it is complaining about a missing operator at the bool's and qint32's but they should be available according to the documentation.



O:/projects/Post_Program/server.cpp:107: error: no match for 'operator>>' in 'in >> server->Server::serverPort'

Lawand
14th June 2009, 17:12
Wait a minute, aren't those members private? how are you accessing them directly?

eekhoorn12
14th June 2009, 20:17
To test it i made the public.

Lawand
14th June 2009, 21:11
That error you're getting doesn't necessarily mean what you think it means, sometimes GCC errors are ambiguous.

I copied all the code as-is into a project in my PC then added the two line I told you about (the declarations) and it turend out that you should un-hint the "#include <QDataStream>" and the error will go away...

eekhoorn12
14th June 2009, 21:34
I tried it and it works. Thanks everything works now.

Lawand
15th June 2009, 11:04
It's good to know that :)