Search code examples
c++qtqiodeviceqbuffer

Qt QBuffer bytes written cannot be read


A bit of confusion here: I'm trying to do this:

QBuffer _ourLogMessageBuffer;
QByteArray theLogMessage;
...
qDebug() << "Writing " << theLogMessage.size() << " bytes to buffer\n";
qint64 numberOfBytes - _ourLogMessagesBuffer.write(theLogMessage);
qDebug() << "Wrote " << numberOfBytes << " bytes to buffer\n";
qDebug() << "Buffer has " << _ourLogMessagesBuffer.bytesAvailable()
         << " bytes available to read (after write)\n";

This outputs the following:

Writing 196 bytes to buffer
Wrote 196 bytes to buffer
Buffer has 0 bytes available to read (after write)

That last line really confuses me. I thought the return value from the .write() method was supposed to say how many bytes were written? Why would they not be available?

And, later, I attempt the following:

qDebug() << "Buffer has " << _ourLogMessagesBuffer.bytesAvailable()
         << " bytes available to read (before read)\n";
char logMessageBytes[565];
qint64 numberOfBytes = _ourLogMessagesBuffer.read(logMessageBytes, 565);
qDebug() << "Read " << numberOfBytes << " bytes from buffer\n";

Considering the previous bytesAvailable result, the output of these calls aren't too surprising. They output the following:

Buffer has 0 bytes available to read (before read)
Read 0 bytes from buffer

So I feel like I'm missing a step, and that you have to do something between writing and the data being available to read. Perhaps some sort of seek or something? But I seem to be missing where it says that in the documentation.

Any tips would be appreciated. Thank you!


Solution

  • You need to seek back to the position you want to read from:

    _ourLogMessagesBuffer.seek(0);
    

    Then you will be able to see an appropriate amount of bytesAvailable. If you think about as a (physical) pointer to a position on a tape, it makes sense. As you write, the pointer moves to the end where it can write more data. Any tape ahead of the pointer is "blank"; there's nothing to read (for a "blank" tape, a new or empty buffer).

    When just writing, the position is automatically updated for you. But if you want to read data you already wrote, you need to tell it to go back.

    An exception to this is with, say, a file format. If we are modifying an existing file, we could update a fixed-length timestamp in one part, then immediately read a couple bytes denoting the length of an "author" string, and then read that string in. For that, we would not need a seek as all the data is contiguous, and the write and read functions handle moving the position within the file (buffer) automatically.

    If you have non-contiguous reads/writes, you need to seek. Otherwise, it can't read your mind on where you want to read from.