PDA

View Full Version : QFile::atEnd() problem?



lvi
5th August 2008, 12:04
I have a problem with QFile::atEnd(). I have the following code (simplified):


while (!partFile->atEnd()) {
line = partFile->readLine();
/* Do stuff with "line" */
}

This works fine on Linux and on MacOS X. But on Windows, this results in an infinite loop, i.e. atEnd() never returns true. Of course, the file exists and I can read from it.

I have noticed more oddities in QFile across platforms ("\" vs. "/" inconsistincies), but this one is kind of hard to work around...
Any ideas on what causes this and/or how to fix it?

wysota
5th August 2008, 13:13
atEnd() works fine for me on Windows, your problem has to be related to something else... maybe readLine() doesn't read the line? Does the file contain proper line endings for the platform (\r\n in case of Windows)?

lvi
5th August 2008, 13:20
readLine() is working fine: I get the data from the file. So I'd think that the line terminators are fine. Does atEnd() check for EOF? I can't understand why the end of file wouldn't be detected...

wysota
5th August 2008, 19:32
Try with different files. Or make a simple test:

bool t1 = file.atEnd();
qDebug() << t1;
file.readAll();
t1 = file.atEnd();
qDebug() << t1;
Second debug statement should display true.

Your current code is correct only when a file ends with an empty line, otherwise you won't be reading the last line.

lvi
5th August 2008, 21:55
I'm not sure if this result is relevant:



while (partFile->canReadLine()) {
line = partFile->readLine();
/* Do stuff with "line" */
}

Now the loop is not entered at all, i.e. partFile->canReadLine() returns false from the beginning. This happens on Linux!
When I open the file with an editor, I see newlines, so I must be doing something wrong here.
For completeness: partFile is a QTemporaryFile written by some other thread that passes the partFile pointer to this thread (the one that's is doing the reading) trough a queue system.
I am absolutely clueless here. Is there any behaviour of QIODevice, QFile or QTemporaryFile that I'm overlooking?

wysota
5th August 2008, 23:57
Maybe despite the fact that you see newlines there are no newlines there? :)

BTW. Accessing QObjects across threads is Very Bad, so try redesigning your architecture.

lvi
6th August 2008, 10:00
Maybe despite the fact that you see newlines there are no newlines there? :)
That would be strange... But I'll look into it...



BTW. Accessing QObjects across threads is Very Bad, so try redesigning your architecture.
Why? I'll admit this is my first multithreaded application. I had thought that as long as I make sure the objects are only accessed by one thread at the time, it should be OK. Only one thread can write data to the objects, the other threads are only reading (i.e. object->getSomeProperty() ).

wysota
6th August 2008, 10:56
Why?
Because QObject is not reentrant nor thread-safe.


I had thought that as long as I make sure the objects are only accessed by one thread at the time, it should be OK.
The point is that you are not the only one accessing them.


Only one thread can write data to the objects, the other threads are only reading (i.e. object->getSomeProperty() ).

That doesn't matter. Imagine you are reading some data and at the same time some other thread changes it and as a result you read partially the new and partially the old data.

lvi
6th August 2008, 11:22
You make a good point. I did read http://doc.trolltech.com/4.4/threads.html#reentrancy-and-thread-safety, but it seems I have not yet fully understood. If I understand correctly, I should only use the approach I use now if I properly use mutexes, or pass the object by reference in a signal-slot setup?

To come back to the original problem: I have found that the problem may be caused my socket reading (where the data in the file comes from). Not yet sure how to fix it, but apparently, there's some \r and \n mess going on there, i.e.: \r\n from the network protocol, \n from writing to file, something like that.

wysota
6th August 2008, 13:37
If I understand correctly, I should only use the approach I use now if I properly use mutexes, or pass the object by reference in a signal-slot setup?
Not really. You can't call directly methods from QObjects across threads unless they are explicitely mentioned as thread-safe. So yes, you can connect to them using signals and slots to transfer data across threads, but you can't pass QObjects themselves as arguments to signals or call the sending object's methods from within the slot living in another thread than the object.


To come back to the original problem: I have found that the problem may be caused my socket reading (where the data in the file comes from). Not yet sure how to fix it, but apparently, there's some \r and \n mess going on there, i.e.: \r\n from the network protocol, \n from writing to file, something like that.

Dump the data directly to a file without modifying anything and inspect it manually.