Results 1 to 5 of 5

Thread: Why doesn't Qt have an async local file API and what to do instead?

  1. #1
    Join Date
    Jul 2009
    Posts
    139
    Thanks
    13
    Thanked 59 Times in 52 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Why doesn't Qt have an async local file API and what to do instead?

    What do people do when they need to read a lot of data from a local file without blocking the main thread? Is the only method to fire up another thread? There is QNetworkAccessManager which will work with local files but it only does whole files. Any ideas? Many people must have faced this problem, or are hard disks fast enough that it usually doesn't matter?

    Has anybody used QNetworkAccessManager for this purpose? Any issues I should be aware of, if I use it?

  2. #2
    Join Date
    Jan 2006
    Location
    Belgium
    Posts
    1,938
    Thanked 268 Times in 268 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows
    Wiki edits
    20

    Default Re: Why doesn't Qt have an async local file API and what to do instead?

    Reading and writing to a file is synchronous when you read or write the data in one continuous block. If you do that, as you know, it will block everything else till it is done. For small files, this delay is neglectful but for large files you might want to read in blocks.

    QFile lets you do that. Create a file reader or writer that writes in "chunks" rather than the whole thing at once.
    You can even use QTextStream or QDataStream to do that.

    Edit: Note though that QFile doesn't implement the readyRead() signal for example.
    I would create a file reading class that implements a signal that says that a chunk has been read or can be written.
    Then I would connect this signal to a slot and keep reading or writing chunks.
    In the mean time, your program has time to process other events.

    Alternatively, as you said, you could use threads too, but be careful, you need to add a great deal of extra code to prevent multiple threads accessing the same file at the same time for example (among other things)
    Last edited by tbscope; 20th June 2010 at 17:56.

  3. The following user says thank you to tbscope for this useful post:

    numbat (21st June 2010)

  4. #3
    Join Date
    Sep 2009
    Location
    UK
    Posts
    2,447
    Thanks
    6
    Thanked 348 Times in 333 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Why doesn't Qt have an async local file API and what to do instead?

    I've used threads to do file i/o before as the file i/o I was doing was typically over a network which could be slow (ie, it could take several seconds depending on network load) and I didn't want to application to show the "Not responding" message because I wasn't processing events.

    Generally however, I don't bother. File i/o is infrequent enough (and mostly local based) to not worry about.

  5. The following user says thank you to squidge for this useful post:

    numbat (21st June 2010)

  6. #4
    Join Date
    Jul 2009
    Posts
    139
    Thanks
    13
    Thanked 59 Times in 52 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Why doesn't Qt have an async local file API and what to do instead?

    Tbscope and Fatjuicymole, thanks a lot. Tbscope, I like your idea of chunks, but I'm not sure when to read them, because as you not QFile does not emit readyRead. I suppose I could use a zero timer, so that the event loop is pumped between each chunk read. However, this means the disk will not be operating while events are being processed. For maximum performance, I'm leaning towards using the chunk idea, but in a separate dedicated thread. Thanks again.

  7. #5
    Join Date
    Jul 2009
    Posts
    139
    Thanks
    13
    Thanked 59 Times in 52 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Why doesn't Qt have an async local file API and what to do instead?

    OK, I did a rough implementation. It doesn't yet contain error handling or cleanup, but I was interested in what you think. The basic idea is a single thread that caches file handles and serves read requests as they come in (via the queued signal/slot).
    Usage:
    Qt Code:
    1. FileReader fr;
    2. fr.start();
    3.  
    4. FileReaderFile frf(&fr, "/home/somefile");
    5. connect(&frf, SIGNAL(dataAvailable(QByteArray, int, int)), SLOT(dataAvailableEvt(QByteArray, int, int)));
    6. frf.addReadRequest(0, 100000);
    7. frf.addReadRequest(100000, 100000);
    To copy to clipboard, switch view to plain text mode 
    Implementation:
    Qt Code:
    1. /*
    2.  * FileReaderFile
    3.  */
    4. FileReaderFile::FileReaderFile(FileReader *fr, QString filename) :
    5. m_filename(filename), m_fr(fr)
    6. {
    7. connect(this, SIGNAL(addFile(QString,FileReaderRequest*)), fr, SLOT(addFileEvt(QString, FileReaderRequest*)));
    8. }
    9.  
    10.  
    11. void FileReaderFile::addReadRequest(int start, int count)
    12. {
    13. FileReaderRequest * fri = new FileReaderRequest(m_fr, start, count);
    14. connect(fri, SIGNAL(dataAvailable(QByteArray, int, int)), this, SIGNAL(dataAvailable(QByteArray, int, int)));
    15. emit addFile(m_filename, fri);
    16. }
    17.  
    18. /*
    19.  * FileReaderRequest
    20.  */
    21. FileReaderRequest::FileReaderRequest(FileReader *fr, int start, int count) :
    22. m_start(start), m_count(count)
    23. {
    24. moveToThread(fr);
    25. }
    26.  
    27. bool FileReaderRequest::process(QFile *file)
    28. {
    29. /* Read the request, then delete ourselves. */
    30. file->seek(m_start);
    31. QByteArray ba = file->read(m_count);
    32. emit dataAvailable(ba, m_start, ba.length());
    33. deleteLater();
    34. return true;
    35. }
    36.  
    37. /*
    38.  * FileReader
    39.  */
    40. FileReader::FileReader()
    41. {
    42. moveToThread(this);
    43. }
    44.  
    45. void FileReader::addFileEvt(const QString & filename, FileReaderRequest *fri)
    46. {
    47. QFile * file;
    48. if (m_files.contains(filename))
    49. {
    50. file = m_files.value(filename);
    51. }
    52. else
    53. {
    54. file = new QFile(filename);
    55. file->open(QIODevice::ReadOnly);
    56. m_files.insert(filename, file);
    57. }
    58.  
    59. fri->process(file);
    60. }
    61.  
    62. void FileReader::run()
    63. {
    64. exec();
    65. }
    To copy to clipboard, switch view to plain text mode 

Similar Threads

  1. QDesktopServices open url & local file & pdf or doc
    By patrik08 in forum Qt Programming
    Replies: 9
    Last Post: 14th April 2012, 04:42
  2. Opening local flash(.swf) file in QtWebKit?
    By DanLT3 in forum Qt Programming
    Replies: 1
    Last Post: 24th March 2011, 15:22
  3. Replies: 7
    Last Post: 14th June 2010, 02:42
  4. Replies: 1
    Last Post: 9th May 2008, 14:49
  5. Password on local file/folder
    By icebox25 in forum Qt Programming
    Replies: 3
    Last Post: 13th April 2007, 16:33

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.