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

Can't reset pos in QIODevice (QFile) to beginning if device was set to WriteOnly mode at one point



  • Hello.

    I encountered a problem for which I can't seem to find an answer. Here's some code:

    void prepareDeviceForReading(QIODevice* device)
    {
        qDebug() << device->atEnd() << device->openMode();
        device->close();
        
        qDebug() << device->atEnd() << device->openMode();
        device->open(QIODevice::ReadOnly);
        
        if (device->atEnd()) device->reset();
        qDebug() << device->atEnd() << device->openMode();
    }
    // ...
    
    QFile* myFile = new QFile(myPath);
    myFile->open(QIODevice::WriteOnly);
    //... do some stuff
    prepareDeviceForReading(myFile);
    

    I'll get the following output for the code above:

    true OpenMode( "WriteOnly" )
    true OpenMode( "NotOpen" )
    true OpenMode( "ReadOnly" )
    

    It is clearly seen, that even though I call device->reset() the qDebug output shows that the position is still at the end of the file, thus making any read impossible. Calling device->seek(0) produces the same result. Interestingly, this is not a problem if the device was set to ReadOnly mode and the pos was left at the end:

    myFile->open(QIODevice::ReadOnly);
    myFile->skip(myFile->size());
    //... do some stuff
    
    prepareDeviceForReading(myFile);
    

    In this case the output is the following:

    true OpenMode( "ReadOnly" )
    true OpenMode( "NotOpen" )
    false OpenMode( "ReadOnly" )
    

    Clearly, the position was reset to the beginning as expected. The same result is possible with ReadWrite mode as well:

    myFile->open(QIODevice::ReadWrite);
    myFile->skip(myFile->size());
    //... do some stuff
    
    prepareDeviceForReading(myFile);
    
    true OpenMode( "ReadOnly|WriteOnly" )
    true OpenMode( "NotOpen" )
    false OpenMode( "ReadOnly" )
    

    So could anyone please explain what is so special about WriteOnly mode, that the position can't be reset to the start even if the mode was switched to ReadOnly afterwards? Is this a bug?

    Thanks for reading.

    P.S.: As per request:
    Qt: 5.13.2
    GCC: 9.2.0
    OS: Linux 4.19.97


  • Lifetime Qt Champion

    Hi,

    You should add which version of Qt you are using as well as OS you are running.



  • Oh, sorry, added version info to end of the original post as requested.


  • Lifetime Qt Champion

    Can you also provide a minimal compilable example ?
    That way we all can check the issue the same way.



  • @PusRob
    I'm not saying what you report is not a bug, but:

    • Just in case:

    Some subclasses, such as QFile and QTcpSocket, are implemented using a memory buffer for intermediate storing of data.
    For this reason, QIODevice allows you to bypass any buffering by passing the Unbuffered flag to open().

    Just for testing purposes, try making your open()s unbuffered in case that alters behaviour?

    • Interestingly, this is not a problem if the device was set to ReadOnly mode and the pos was left at the end

    myFile->open(QIODevice::ReadOnly);
    myFile->skip(myFile->size());

    As a workaround, can you (test existing open file for read-only and) do this skip() to make your re-open work reliably?

    • Check the return result of your device->reset(), just so we know whether that is complaining. Similarly for the device->open(QIODevice::ReadOnly);.

    I presume that when the outside world opened the file WriteOnly it did write some data to the file?! Because

    QIODevice::WriteOnly 0x0002 The device is open for writing. Note that, for file-system subclasses (e.g. QFile), this mode implies Truncate unless combined with ReadOnly, Append or NewOnly.

    Immediately after opening with plain WriteOnly the file gets truncated to 0 length, so at that point re-opening ReadOnly will always return atEnd() as true!

    Does code behave any differently if the write mode was opened WriteOnly | Append?

    Lastly, replace the device->open(QIODevice::ReadOnly); by a fresh QFile::open(QIODevice::ReadOnly) on the same file. We want to ensure that the bad behaviour is only exhibited when an existing, open QIODevice is used, not when a new one against the same file is used instead.

    Then you are ready to report the bug :)



  • @JonB

    Thanks for the extensive guide to debug the problem. It would seem you were right about the file being truncated:

    Immediately after opening with plain WriteOnly the file gets truncated to 0 length, so at that point re-opening ReadOnly will always return atEnd() as true!

    I had a prepared file filled with data, then at some point I opened it with WriteOnly, which then got truncated to 0 immediately. I simply assumed that truncation would only happen once the writing starts, but obviously I was wrong. Somehow I missed the following part from the documentation:

    If possible, the device is truncated before it is opened.

    Thanks for the help, marking the thread as solved.



  • @PusRob said in Can't reset pos in QIODevice (QFile) to beginning if device was set to WriteOnly mode at one point:

    I had a prepared file filled with data, then at some point I opened it with WriteOnly, which then got truncated to 0 immediately.

    Whoops :)


Log in to reply