Qt World Summit: Submit your Presentation

QDataStream/QTextStream file format custom versioning

  • What is the equivalent way to setup a versioning on data stream under QT similar to MFC's

    I could only find "void QDataStream::setVersion(int v)", which sets QT version of an object, but not a custom, your own, version for a custom object.

    Oftentimes, when developing operator<<(QDataStream &is) for a custom object, you need to make a split by a version of file format for this object. If you deal with one simple object, you may keep version variable, which gets assigned in the beginning of file loading and then use a switch by its value when needed. However, when an object gets rather complex with many sub-objects, keeping the file version inside each of sub-objects becomes quite difficult to arrange if not impossible in a meanigful way.

    I am used to a code similar to this

    @MyObject::operator<<(QDataStream &is)
    int version_of_file_fomat;
    version_of_file_fomat << is;
    suboject1 << is;
    suboject2 << is;

    subojectAny::operator<<(QDataStream &is)
    //this object is not aware of MyObject, and
    //the internal variables of MyObject are not available here
    //then simply get the file format version from the incoming stream properties
    int version_of_file_fomat = is.get_file_format_version();
    case 1: blah break;
    case 2: blah break;
    However, I could not find a function under QDataStream, which would allow me to implement such or a similar code.

    I tried to define my own MyDataStream derived from QDataStream, but then you loose ability to call any standard << or >> operators, unless you re-define them in MyDataStream, which would be a lot of excessively unnecessary work.

    What is the proper QT solution for a custom file format versioning?

  • Your code can be realized with dynamic properties on QDataStream.
    In your case:
    @is.setProperty("my-data-version", version_of_file_format);@
    and then
    @version_of_file_format = is.property("my-data-version").toInt()@

    For cleanliness you should probably store the magic string "my-data-version" in some central constant.

    //EDIT: Just incase you're wondering, this is possible because all QObject instances have this dynamic property capability.

  • This is great. Thank you very much. My the only concern would be performance, since I have thousands of little objects to load/save, and each of them will call property() which does a string look up. It is probably not too bad, since it is going to have just one custom property and look up will be quick, but it will still do string comparison, at least once for each object, will not it? I will make one character string like "v" to minimize the impact, but I would expect that loading time may increase like twice or so on little objects.

    I just wondering is that how QT developers really intended for people to implement it? Whenever anybody have a data file, it ends up with versions - I would expect this to be a common basic issue. I felt pretty surprised that I could not find a solution in the QT Assistant, which is normally very helpful. There must be a recommended efficient way with the minimum impact on the performance.

    Would you think we should submit an idea to add a simple integer variable to the object QData/Text/Stream for versioning to QT developers? I am new to this community and do not yet know a proper way of contacting the developers, but I really want to make sure first that it would be worth of bothering them.

  • In fact QDataStream appeared not to be a QObject, but there is device(), which return QIODevice, which is a QObject and your idea worked fine.

    Unfortunately, I was correct on performance issue, the loading time of a 3GB example data file has increased from 47 to 80 sec - almost twice. It is kind of unacceptable for me.

    Please, does anyone can point me to a document which describes a QT officially recommended way of a data file versioning implementation?

Log in to reply