Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Can't reset pos in QIODevice (QFile) to beginning if device was set to WriteOnly mode at one point

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

Scheduled Pinned Locked Moved Solved General and Desktop
7 Posts 3 Posters 980 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • P Offline
    P Offline
    PusRob
    wrote on last edited by PusRob
    #1

    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

    JonBJ 1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi,

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

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      0
      • P Offline
        P Offline
        PusRob
        wrote on last edited by
        #3

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

        1 Reply Last reply
        0
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by
          #4

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

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          1 Reply Last reply
          1
          • P PusRob

            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

            JonBJ Offline
            JonBJ Offline
            JonB
            wrote on last edited by JonB
            #5

            @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 :)

            P 1 Reply Last reply
            2
            • JonBJ JonB

              @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 :)

              P Offline
              P Offline
              PusRob
              wrote on last edited by
              #6

              @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.

              JonBJ 1 Reply Last reply
              1
              • P PusRob

                @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.

                JonBJ Offline
                JonBJ Offline
                JonB
                wrote on last edited by
                #7

                @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 :)

                1 Reply Last reply
                0

                • Login

                • Login or register to search.
                • First post
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • Users
                • Groups
                • Search
                • Get Qt Extensions
                • Unsolved