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 -
Hi,
You should add which version of Qt you are using as well as OS you are running.
-
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 thedevice->open(QIODevice::ReadOnly);
.
I presume that when the outside world opened the file
WriteOnly
it did write some data to the file?! BecauseQIODevice::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-openingReadOnly
will always returnatEnd()
as true!Does code behave any differently if the write mode was opened
WriteOnly | Append
?Lastly, replace the
device->open(QIODevice::ReadOnly);
by a freshQFile::open(QIODevice::ReadOnly)
on the same file. We want to ensure that the bad behaviour is only exhibited when an existing, openQIODevice
is used, not when a new one against the same file is used instead.Then you are ready to report the bug :)
-
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 :)