[SOLVED] QFile::size() always returns 0, even when it shouldn't



  • About a "week ago":http://qt-project.org/forums/viewthread/31519 I described a function in my application that invokes mysqldump. That part works great but now I'm having trouble determining if the dump operation succeeded.

    I'm using QFile::size to check the filesize on the output file created by the dump. If the dump operation succeeded, the file should contain text data. If the dump failed (for instance, because the user entered the wrong password) QProcess still creates the output file but it would be empty, i.e. 0 bytes in size. I could then mark the bad file for deletion.

    Unfortunately, QFile::size always returns zero even if the size is checked when the file is open ("output" is a QFile object created higher up in the function):

    @

    /* See if the dump was successful by checking output file size. If the file size is zero,
       it's safe to assume the file is empty and the dump failed.
    */
    qint64 size=0;
    
    if(output.open(QFile::ReadOnly| QIODevice::Text)){
    size = output.size();
    cout << "file size: " << size << endl;
    output.close();
    }
    
    QMessageBox m;
    
    if(size==0){
        m.critical(this,"RoboJournal","Output operation failed.");
        return false;
    }
    
    m.information(this,"RoboJournal","Output operation succeeded.");
    return true;
    

    @

    I'm not sure why this is happening. I've eliminated the possibility of it being because the QFile object doesn't exist when instantiated because QFile::size() returns 0 even when I overwrite an existing file. This code is being built against Qt 4.8 on Linux.

    Is this even the best way to check the success of the mysqldump operation?



  • Hi pwizard.
    Did you tray errorString() to verify if there are same error with file?
    @
    if(output.open(QFile::ReadOnly| QIODevice::Text)){
    size = output.size();
    cout << "file size: " << size << endl;
    output.close();
    }
    else{
    cout << output.errorString() << endl;
    }
    @

    Hope its util.
    Regad



  • @
    cout << output.errorString().toStdString() << endl;
    @

    outputs "Unknown error".

    At this point, I know the app is at least trying to open the file because the app prints the cout << "file size: " << size << endl; string.



  • I just tried creating another QFile object with the same path as "output" just in case Qt couldn't tell that the original file had changed. Unfortunately, it didn't work--size() is still returning 0.



  • I'm still trying to solve this and I just noticed something very strange:

    If I call QFile::size directly, it works ("dump" is a QFile):

    i.e.
    @cout << "File size: " << dump.size() << " bytes. " << endl;@

    outputs

    File size: 38080 bytes.

    However, dump.size() always returns 0 if I bind it to a variable before using it:

    i.e.

    @qint64 size=dump.size();
    cout << "File size: " << size << " bytes. " << endl;
    @

    outputs

    File size: 0 bytes.

    The output should be identical but it's not. Could this be a bug in Qt or is something else going on here?



  • what file do you wanted to open ,are you sure your file could be open succeed? or the file is existed?


  • Moderators

    Hi,

    [quote author="pwizard" date="1381094564"]I'm still trying to solve this and I just noticed something very strange:

    If I call QFile::size directly, it works ("dump" is a QFile):

    i.e.
    @cout << "File size: " << dump.size() << " bytes. " << endl;@

    outputs

    File size: 38080 bytes.

    However, dump.size() always returns 0 if I bind it to a variable before using it:

    i.e.

    @qint64 size=dump.size();
    cout << "File size: " << size << " bytes. " << endl;
    @

    outputs

    File size: 0 bytes.[/quote]That does look strange. I haven't been able to reproduce it on my PC though (Qt 5.1.1, Windows 7 64-bit, MSVC 2010, 32-bit) -- I created a file that's 38080 bytes long and QFile gave me the correct size when I tried to query it in different ways.

    My first thought was that it could be to do with file caching/flushing, but your QFile is only reading and not writing, so that's unlikely to be the cause.

    Some things you can try, to help pinpoint the issue:

    • See if the issue exists on both debug and release builds
    • Convert your result to a regular int instead of qint64 before printing
    • Print to qDebug() instead of std::cout
    • Read the size without opening the file
    • Upgrade to Qt 4.8.5 or Qt 5.1.1

    A possible workaround:

    • Do QFile::readAll() and check the size of the QByteArray instead

    [quote]Is this even the best way to check the success of the mysqldump operation?[/quote]I would check for error messages from mysqldump directly.



  • bq. what file do you wanted to open ,are you sure your file could be open succeed? or the file is existed?

    For now, I'm writing these files to /tmp on Linux Mint 15 (anything can read/write in /tmp so I'm using it for debugging purposes). I know these files are good because I can read them with no problem whatsoever in a text editor. The app is being built against the Qt 4.8 in the Mint repositories.

    bq. Do QFile::readAll() and check the size of the QByteArray instead

    I just tried that and QByteArray::size() also returns 0. I also tried QByteArray::isEmpty() and that returns true even when a file has text in it.

    Could this have something to do with the operating system?

    bq. Convert your result to a regular int instead of qint64 before printing

    already tried, made no difference.

    bq. Read the size without opening the file

    Size still returns 0.

    bq. Upgrade to Qt 4.8.5 or Qt 5.1.1

    I'm stuck with the 4.8.4 version in the Mint repositories for now. The app currently doesn't build with Qt5. I suppose I could port the app ahead of schedule if I really had to.

    bq. See if the issue exists on both debug and release builds

    Issue affects them both.


  • Moderators

    [quote author="pwizard" date="1381176221"][quote]Do QFile::readAll() and check the size of the QByteArray instead[/quote]

    I just tried that and QByteArray::size() also returns 0. I also tried QByteArray::isEmpty() and that returns true even when a file has text in it.

    Could this have something to do with the operating system?[/quote]Aha, now we're getting warmer.

    Has mysqldump fully flushed and closed the file before you tried to check the file size? The data could still be in the operating system's cache, and hasn't been fully written to disk.

    Try this:

    Make a dump

    Then, use an external text editor to open the file and verify that everything has been written

    AFTER verifying, close the file, launch another program and call QFile::size() -- I'm quite sure you should see the correct size now



  • You are right...I tested a file that has been in my /tmp since yesterday and QFile::Size() returned the correct value.

    It looks like the problem is due to the file size being checked prematurely (before mysqldump is finished with it). Is there a reliable way to have QProcess force my program to wait until the file has been completely written to disk/flushed before checking the file size?


  • Moderators

    I'm not 100% sure, but I think all file buffers are flushed when the process exits normally. You could wait till your QProcesses has exited (i.e. when it emits the finished() signal, or when waitForFinished() returns) before reading the file.



  • Attaching a slot to QProcess::finished() did the trick, thanks for the help!

    I also needed to use QProcess::WaitforFinished() to force the app to wait. Without that, the function would end before QProcess could emit the finished signal (preventing the slot from working).


  • Moderators

    [quote author="pwizard" date="1381354862"]Attaching a slot to QProcess::finished() did the trick, thanks for the help![/quote]You're welcome :) Please edit your original post and add "[SOLVED]" to your title.

    [quote]I also needed to use QProcess::WaitforFinished() to force the app to wait. Without that, the function would end before QProcess could emit the finished signal (preventing the slot from working). [/quote]Sounds like your QProcess is a local variable?

    Generally you would allocate a QObject on the heap so that it doesn't get destroyed before it can emit all its signals. This way, you can reuse the object too. Call QObject::deleteLater() when you don't need it anymore.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.