camino
camino

Reputation: 10594

Uncharacteristic file-read operation using QTextStream in Linux

I am using linux platform (Ubuntu) and QT4.7.4 ,

first, I create a test file "test.txt" using vi , just write 100000 lines "1234567890" in it,

Then I compile & run the codes below, to my supervising ,it enter infinite loop ,

any ideas about it ? Thanks!

int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);
    QString str;

    QFile file("./test.txt");
    if ( file.open(QIODevice::ReadOnly | QIODevice::Text) ) {

        QTextStream ts( &file );
        while(!ts.atEnd()) {
            str = ts.read(10240);
            qDebug()<<"s:"<<ts.status()<<":"<<ts.atEnd()<<":"<<str.count()<<":"<<ts.pos();

        }
    }
    return app.exec();
}

here is the qdebug output:

s: 0 : false : 10240 : 10240 
s: 0 : false : 10240 : 20480 
s: 0 : false : 10240 : 51200 
s: 0 : false : 10240 : 112640 
s: 0 : false : 10240 : 235520 
s: 0 : false : 10240 : 481280 
s: 0 : false : 10240 : 972800 
s: 0 : false : 10240 : -1 
s: 0 : false : 10240 : -1 
s: 0 : false : 10240 : -1 
s: 0 : false : 10240 : -1 
s: 0 : false : 10240 : -1 
s: 0 : false : 10240 : -1 
s: 0 : false : 10240 : -1 
....

here are some infos about test.txt

$du  -sh test.txt 
1.1M    test.txt

$wc -c test.txt 
1100011 test.txt

$du -S test.txt 
1076    test.txt

Upvotes: 1

Views: 380

Answers (3)

alexisdm
alexisdm

Reputation: 29896

This was a bug in QTextStream::pos, which prevented to use pos() with files bigger than 16KB (I think), it seems to have been fixed somewhere between Qt 4.7 and 4.8.

But anyway, using QTextStream::pos() inside that loop is terribly impacting the reading speed, so, you should avoid it.

Upvotes: 1

ScarCode
ScarCode

Reputation: 3094

Somehow your seek pointer lost track somewhere. This may be in internal call to seek function made by pos() function.

So try to seek your pointer manually in every iteration. I suggest reading small chunks of data in iteration.

Try this

       int pos=0;
       QTextStream ts( &file );
       while(!ts.atEnd()) {
           pos+=5120;
           {
               str = ts.read(5120);

               qDebug()<<"s:"<<ts.status()<<":"<<ts.atEnd()<<":"<<str.count()<<":"<<ts.pos();
               ts.seek(pos);//manually seeking to current position
           }

       }

This should work.

And you will see s: 0 : true : (final-chunk-data-size) : (size-of-your-test.txt-file) as final line in your qdebug output.

The problem is with ts.pos(); in line qDebug()<<"s:"<<ts.status()<<":"<<ts.atEnd()<<":"<<str.count()<<":"<<ts.pos(); Since QTextStream is buffered, the pos() function may have to seek the device to reconstruct a valid device position.[there is a chance that, if you use QFile and TextStream in conjunction, the text stream's internal position will be out of sync with the file's position, that way this seek function used inernally by pos() function may go terribly wrong!!]

So if you use it without calling ts.pos() it will go alright. You don't have to manually seek. Otherwise, if you add ts.pos(), you should manually seek.

See the sequence of pos output, it always add (10240 + the previous position) to the previous position value in every pos() call. that means it jumps by an amount of previous position values in every pos() call as it is out-of-synch with file's position by an amount of previous pos. So if you call pos(), that out-of-synch is reflected in your texstream object.

Upvotes: 1

user1427458
user1427458

Reputation:

There seems to be some problem with the file that you are trying to read. Check the file encoding of test.txt. If you see the size of data read, you will see anomalies with the text read, the reading moves from 20K to 50K to 100K.

The code is fine and working for me.

Upvotes: 0

Related Questions