Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

How would a QFileWriter class work out?



  • Over the last couple days, I've been making a FileWriter class. Essentially, working like this.

    FileWriter fw;
    fw.Write("text.txt", *insert any QT object here*);
    

    I think this would make a great addition to the QT library. Maybe not my code, just the concept in general. There's a lot of repetitive tasks and human error opportunities in writing directly to the disk. Aside from a couple quirks I'm working out creating directories, it's very possible. There are just a lot of hoops to jump through for such a basic thing. C++, tsk tsk.



  • @jamieyello
    What is the question here? Is it how to serialize any QObject for writing (which I imagine is difficult/impossible)?


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    What you described makes me think of QFile with QTextStream.

    Isn't it ?



  • @SGaist
    You can serialize any arbitrary QObject to QTextStream? I would have expected them to be non-serializable (all those internal pointers etc.!)?


  • Lifetime Qt Champion

    No you can't because there's no way to generically save a data structure without some base plumbing. What you can do is implement the QTextStream and/or QDataStream operators for the classes you want to serialise.



  • @SGaist
    OK, that's what I would have expected, thanks. So the point is the OP will need to write that text serialization himself, I think he was expecting it to be available in Qt "out-of-the-box".


  • Lifetime Qt Champion

    You can automate some stuff with introspection but it's still you the developer that should provide the correct way to serialise deserialise its classes.



  • Hi!

    The following function I've tested with QList<QByteArray>'s and QList<QString>'s, and it reads/writes (both types in the same file as well). The caveat being it isn't creating the necessary folders yet. I did see a long list of data types QDataStream supports, which for the life of me I can't find anymore. I guess I would be talking about a simplified version of QDataStream.

    // Writes given QT object to disk.
     template <typename T> // Declared and defined in the .h file to avoid undefined reference errors
     bool Write(QString name, T const & object, bool append = false)
     {
         if (!append) Delete(name); // custom function
    
         QFile file(name);
         QDataStream stream(&file);
    
         if (file.open(QIODevice::WriteOnly | QIODevice::Append)) {
             stream << object;
         }
         else {
             qDebug() << "FileWriter::Write (" + name + ") Error: " + file.errorString();
             return false;
         }
         file.close();
    
         return true;
     }
    

    Reading the data, (from an old function I haven't made modular)

    QString CMM::LoadFromFile(QString cmmFile)
    {
        Clear();
        QFile qfile(cmmFile);
    
        if (!qfile.open(QIODevice::ReadOnly)) return "Could not open .cmm file (" + cmmFile + "), Error message; " + qfile.errorString();
        QDataStream stream(&qfile);
    
        stream >> fileNames;
        stream >> data;
    
       // Everything below just makes sure the data is correct and not corrupted
    
        qDebug() << "fileNames.length() = " << fileNames.length();
        qDebug() << "data.length() = " << data.length();
        qfile.close();
    
        if (fileNames.length() == 0) { return "Invalid .cmm, no content detected."; }
    
        QString integrityCheck = Validate();
        if (integrityCheck != "") { return integrityCheck; }
    
        return "";
    }
    

  • Lifetime Qt Champion

    Except it won't work with QObject based class as they can't be copied.

    By the way it's Qt, QT stands for Apple's QuickTime which I guess is not your target with this class.

    [edit: fixed missing reference to Apple SGaist]



  • @SGaist said in How would a QFileWriter class work out?:

    Except it won't work with QObject based class as they can't be copied.

    By the way it's Qt, QT stands for QuickTime which I guess is not your target with this class.

    My first post was misleading. Obviously not any Q object would work, but a good majority of the types of data you would want to write to the disk do. Ay data type compatible with QDataStream.

    So I guess what I'm trying to say is that this probably could have been easier, that a single class could handle all of that, including folder creation.


  • Lifetime Qt Champion

    I don't say it's not a good idea but it looks like some kind of logger rather than a real load and store mechanism.

    Most applications that uses files to save their objects usually follow a strict format to store and load their document/internal state. There's no one solution fits all. On top of that, the version of QDataStream should be set when doing so to ensure backward/forward compatibility if it makes sense for your application.



  • Alright, I'm really not one to argue here. Worth mentioning that I'm actually using this function internally in an object to just streamline the process, though I can't comment on this being much of a logger.

    I'm actually building a custom .zip format atm. The last little quirk I've got to work out is learning how to write the data without the encoding. If you're still curious, it's all for a mod manager for a certain game, and generally, the only kind of data I'm working with is entirely unrelated to the program itself.

    That's a good tip, setting the version. I wouldn't have thought of that until I ran into problems.



  • It doesn't look like QDataStream has an option to disable the writing of metadata through << operators when using template objects. writeRawData() requires a length field, and I don't believe it's possible to recognize that with a template object. The simple workaround would be to make the template method private with some secondary overload methods that would accept all the different kinds of data I plan on working with and then detect the lengths of the files, but I feel like that would defeat the goal of what I'm going for here.

    I could remove the metadata manually. Looking at the resulting files through a hex editor, it seems simple enough to spot. Not preferable, not very optimized, having to open and close the file twice.


Log in to reply