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

reading and writing a utf16 string inside a qdatastream operator



  • I've got a struct that has a uft16 string inside it. How do i read it in the operator >> and <<..

    Example:

    struct People
    {
        quint32 Id;
        quint16 Name_Legth; // utf16 string length
        QString Name // utf16 string
        quint32 Age;
    };
    
    inline QDataStream &operator<<(QDataStream &readstream, const People &m_people)
    {
        readstream << m_people.Id << m_people.Name_Legth << m_people.Name << m_people.Age;
        return readstream;
    }
    
    inline QDataStream &operator>>(QDataStream &writestream, People &m_people)
    {
        writestream >> m_people.Id >> m_people.Name_Legth >> m_people.Name >> m_people.Age;
        return writestream;
    }
    
    void dosomething()
    {
    	People m_people;
    	QDataStream readstream(Data);
            readstream.setByteOrder(QDataStream::LittleEndian);
    	
    	while(!readstream.atEnd())
            {
                   readstream >> m_people;
    	       m_people.append( m_people );
    	}
    	return;
    }
    

    Is is possible to do something like this?

    inline QDataStream &operator>>(QDataStream &writestream, People &m_people)
    {
        writestream >> m_people.Id >> m_people.Name_Legth;
    
        if(m_people.Name_Legth <= 0)
        {
            m_people.Name = "";
    	writestream >> m_people.Name;
        }
        else
        {
            QByteArray Buffer( m_people.Name_Legth * 2, 0);
            writestream.writeRawData( Buffer.data(), m_people.Name_Legth * 2);
            m_people.Name = QString::fromUtf16(reinterpret_cast<const ushort*>( Buffer.constData()));
    	writestream >> m_people.Name;
        }
        writestream >> m_people.Age;
        return writestream;
    }
    

    What to do about the readstream side. Its also Const.


  • Lifetime Qt Champion

    Why? Simply throw away the superfluous Name_Legth and serialize the rest, QDataStream will do the rest for you.



  • I dont understand? example?


  • Lifetime Qt Champion

    struct People
    {
        quint32 Id;
        QString Name;
        quint32 Age;
    };
    
    inline QDataStream &operator<<(QDataStream &readstream, const People &m_people)
    {
        readstream << m_people.Id << m_people.Name << m_people.Age;
        return readstream;
    }
    
    inline QDataStream &operator>>(QDataStream &writestream, People &m_people)
    {
        writestream >> m_people.Id >> m_people.Name >> m_people.Age;
        return writestream;
    }
    
    


  • I dont see how this can work?

    Lets say the datastream looks like this

    01 00 00 00 - ID
    05 00 - name length 
    64 75 6D 70 6C - name
    34 00 00 00 - age
    

    still doesn't populate the string. Only if i read the rawdata from the buffer.



  • @Styx said in reading and writing a utf16 string inside a qdatastream operator:

    still doesn't populate the string. Only if i read the rawdata from the buffer.

    First question what are you want to do:

    • read/write a QString from/to a file?
    • read/write a UTF-16 string from/to a file and store it in a QString?

    If it is the first, then QDataStream is able to serialize and deserialize a QString, there is nothing else to do. There is also no need of an extra variable to store string length. QString itself knows how long the string is!


  • Lifetime Qt Champion

    Where do you have the bytes from? You must only read and write with QDataStream.



  • Reading them from a Binary File. All strings are utf-16 before the string is the string length of the string.


  • Lifetime Qt Champion

    @Styx said in reading and writing a utf16 string inside a qdatastream operator:

    Reading them from a Binary File.

    You can't use QDataStream for this. You have to write your own parser.


  • Lifetime Qt Champion

    @Styx
    Hi
    So this binary file is NOT one you made saving the People struct?
    I mean you did not save this file yourself, but wants to read it in ?



  • I didnt use qdatastream to write it or read it.

    My program works using writeRawData and readRawData

    Just wondering if it was possible to use operators to read it much like the documents say.

    Long as these binarys have no strings they can be read and written like @Christian-Ehrlicher posted...

    const QVector<People> &getPeople() const; // grabs all the data in the vector to print it to a file.
    

    Only other question i had.. since my get method is const i cant use a binary operator

    inline QDataStream &operator<<(QDataStream &readstream, const People &m_people)
    {
        readstream << m_people.Id << m_people.Name_Legth;
    
        if(m_people.Name_Legth <= 0)
        {
            m_people.Name = "";
    	readstream << m_people.Name;
        }
        else
        {
            QByteArray Buffer( m_people.Name_Legth * 2, 0);
            readstream.readRawData( Buffer.data(), m_people.Name_Legth * 2);
            m_people.Name = QString::fromUtf16(reinterpret_cast<const ushort*>( Buffer.constData()));
    	readstream << m_people.Name;
        }
        readstream << m_people.Age;
        return readstream;
    }
    

    is something like this even possible?


  • Lifetime Qt Champion

    @Styx

    Yes its possible but you cannot do it via
    readstream << m_people.Name;

    as here you read in QString via QDataStream and Qstring would normally add its length
    to the stream before the actual text data.

    But since you did NOT use QDataStream to save the QString, it will read it wrong.

    So you must read back your string using "raw" reading just as you wrote it.

    Its important to understand that all Qt Types can save and load themself. They also save the size for
    strings and containers.

    So if you try to mix it with raw format, you have to be really careful as else it simply will read it wrong.

    As @Christian-Ehrlicher shows, is how Qt does it by itself. No handling of sizes as the classes does that themself.

    So you really are complicating it for your self and I hope there is a good reason as else
    just changing to use QDataStream &operator<< and >> for saving and loading is much
    less error-prone. :)


Log in to reply