0

I'm trying to read an existing file that was created from a QT application using QDataStream, I'm using C# to read it but I can not make work.

Here is my C# code for reading the file: I get no errors just a blank MessageBox.

How can I read file created in QT with QDataStream using C#?

    FileStream readStream;
    string msg = null;
    try {
        readStream = new FileStream(@"C:/MyUsers/SomeFolder/UserNameList.txt", FileMode.Open);
        BinaryReader readBinary = new BinaryReader(readStream);
        msg = readBinary.ReadString();
        MessageBox.Show(msg);
        readStream.Close();
    }
    catch (Exception ex) {
        MessageBox.Show(ex.ToString());
    }

Here is the code used for writing the file in QT.

   QFile UsersNameListFile ("C:/MyUsers/SomeFolder/UserNameList.txt");        
    QString userName = "SomeName";

    QHash<QString, QString> listOfUsers;

    if(!listOfUsers.contains(userName))
    {
        listOfUsers.insert(userName, "Some Text");

        if (UsersNameListFile.open(QIODevice::WriteOnly))
        {
            QDataStream writeToFile(&UsersNameListFile);
            writeToFile.setVersion(QDataStream::Qt_5_1);
            writeToFile << listOfUsers;

            UsersNameListFile.flush();
            UsersNameListFile.close();
        }
    }
fs_tigre
  • 10,650
  • 13
  • 73
  • 146
  • 1
    It is not correct to save with a QDataStream if it is going to read another program that does not use Qt since the format is highly dependent on Qt, and between version and version the format used by QDataStream can vary greatly. – eyllanesc Jul 23 '18 at 14:41
  • Thanks a lot for the clarification. Unfortunately, when the QT application was created, there was no need to read the file from another app as it is now. – fs_tigre Jul 23 '18 at 15:10
  • 1
    My recommendation is that you rewrite your C++ code since QDataStream is not portable outside Qt, or use a Qt wrapper for C# – eyllanesc Jul 23 '18 at 15:20
  • Thank you for the good advice but unfortunately, the QT program is currently installed in about 100 computer now and rewriting the code would imply reinstalling the new app version which would be a little tricky (time-consuming). – fs_tigre Jul 23 '18 at 15:27
  • 1
    see https://stackoverflow.com/questions/33741691/can-we-use-qt-with-c-sharp-to-create-gui, Use QtSharp, also if your software is going to be *massive* I would recommend an update system – eyllanesc Jul 23 '18 at 15:28
  • 1
    Is there any reason you can't use the [`Qt` `C#`](https://gitlab.com/ddobrev/QtSharp) bindings to read/process the file? – G.M. Jul 23 '18 at 15:32

1 Answers1

0

Not a real solution, just too long for a comment.

As pointed out by others in the comments to your question, QDataStream uses a format that is not supposed to be fixed. QDataStream provides you a method to set the version of the format you are using to ensure back compatibility among different Qt versions, but unfortunately the Qt docs is missing the details of each version.

Here, version 13, is the one that is currently available on the official docs. It is not event the latest, this doc page is just not updated very often.

Anyway if you are lucky enough, that is you are using version 13 or the format for QHash and QString is the same for the version you are currently using, you should have a file that starts with an unsigned int 32 that represents the number of elements in your hash map and then for each pair you have two QStrings, each represented again as an unsigned int 32 for the size of the string and then the array of characters encoded in UTF16. Null or empty strings are stored as 0xFFFFFFFF.

Something like this:

HASH_MAP_COUNT, 4 bytes, read as unsigned int 32, tells you how many key,value pairs

FIRST_STRING_KEY, 4 bytes, uint 32, tells you how long is this key

FIRST_STRING_KEY_DATA, read as UTF16 characters

FIRST_STRING_VALUE, 4 bytes, uint 32, tells you how long is this value

FIRST_STRING_VALUE_DATA, read as UTF16 characters

and so on ...

You could try to implement your reading function in C# following this format, and if you still cannot read anything, then go the hard way and check the implementation of the QDataStream& operator<<(QDataStream &out, const QHash<Key, T> &hash) for the specific version of qt that you are using. You should be able to find it in the qdatastream.cpp file.

Hope this can help.

Gabriella Giordano
  • 1,188
  • 9
  • 10