2016-07-21 102 views
1

我正在使用QFile作爲文件讀取器和文件編寫器,以將文件從我的應用程序中複製到USB。我一直在試圖弄清楚爲什麼我的文件複製到USB(帶進度條)需要很長時間。我終於發現,當我關閉用於寫入的QFile對象時,close()操作可以完成實際寫入操作所需的時間。這些文件非常大,我讀/寫16384字節的數據塊,然後向GUI發送信號以增加用戶查看的進度條。我最終在每次寫入後添加了對flush()的調用,因爲我認爲這是由於out流實際上還沒有寫入磁盤。這沒有什麼區別。即將離任的QFile對象的關閉時間仍然比寫入時間(在複製之前和之後以及QFile :: close()的每次調用之前和之後所花費的時間長得多,因此時間碼已被刪除便於閱讀,我也調試並看到它發生)。當然,不要調用close()函數,因爲QFile對象的銷燬會導致它被調用。Qt5 QFile :: close()寫入速度很慢

我的代碼如下(減去錯誤檢查,目標空間檢查等):

void FileCopy::run() 
{ 
    QByteArray bytes; 
    int totalBytesWritten = 0; 
    int inListSize = inList.size(); 

    for (int i=0; !canceled && i<inListSize; i++) 
    { 
     QString inPath = inList.at(i).inPath; 
     QString outPath = inList.at(i).outPath; 
     QFile inFile(inPath); 
     QFile outFile(outPath); 
     int filesize = inFile.size(); 
     int bytesWritten = 0; 

     if (!inFile.open(QIODevice::ReadOnly)) 
     { 
      return; 
     } 

     if (!outFile.open(QIODevice::WriteOnly)) 
     { 
      inFile.close(); 
      return; 
     } 

     // copy the FCS file with progress 
     while (!canceled && bytesWritten < filesize) 
     { 
      bytes = inFile.read(MAXBYTES); 
      qint64 outsize = outFile.write(bytes); 
      outFile.flush(); 
      if (outsize != bytes.size()) 
      { 
       break; 
      } 
      bytesWritten += outsize; 
      totalBytesWritten += outsize; 
      Q_EMIT signalBytesCopied(totalBytesWritten, i+1, inListSize); 
      QThread::usleep(100); // allow time for detecting a cancel 
     } 

     inFile.close(); 
     outFile.close(); 
    } 

    // Other error checking done here 
} 

任何人都可以見得到通過這種方式?我實際上更喜歡進度條移動得更慢,更準確地向用戶顯示副本的狀態,而不是讓進度條在不到複製和關閉實際完成所需時間的一半的時間內讀取100%。我也嘗試使用QSaveFile而不是QFile的輸出,但QSaveFile :: commit()具有相同的確切問題,需要更多的時間來提交比完成實際的複製循環。我認爲這是因爲它下面使用的QFile是從QIoDevice派生的。

我已經考慮轉向使用標準流,但希望在此應用程序中完成文件處理的一致性。儘管如此,如果QFile :: close()需要很長時間才能關閉,那也是可能的。或者標準流有可能會有相同的問題?

我正在使用Qt5.1.1和Qt 1.2.2 VS加載項與VS2010一起使用Win7 32位盒。感謝您的任何建議。

回答

1

在編寫時,操作系統可能只是將寫入內容緩存(快速)。但是,當你關閉文件時,它必須將所有數據刷新到磁盤(慢 - 特別是如果它還沒有寫入的任何)。因此,關閉文件必須等待操作系統將所有數據放入磁盤(USB),並且當時實際上可能全部都是這樣。

操作系統做這種事情的原因當然是加快寫入速度 - 而且當沒有其他事情發生時,他們通常會將數據刷新到磁盤中(因此您並不真正注意實際成本,因爲隨着時間的推移,沒有其他事情正在進行分期付款)。但是,如果你只是寫,然後立即關閉,你會注意到。 注意:替代方案是寫入呼叫速度較慢 - 您仍然會花費相同的實際時間。

+0

正如我懷疑。所以從用戶的角度來看,我寧願看到進度條達到100%,然後複製完成,而不是達到100%,仍然需要等待相同的時間或更長時間複製完成。我現在的問題是,爲什麼在返回之前flush()不會阻塞,直到它實際上將數據刷新到磁盤?如果我能做到這一點,那麼進度條會更準確地描述複製給用戶的狀態。在這種情況下,我實際上對報告複製狀態的準確性更感興趣。 – bmahf

+0

那麼在我調用flush()的時候沒有辦法導致寫入刷新到磁盤?與用戶的界面受到阻礙的原因是,他們不知道爲什麼進度箱坐在100%的時間比到達那裏的時間要長。 – bmahf

+0

您可以嘗試使用'sync','fsync'等進行播放。我不是Windows專家,所以我不知道該怎麼做。 –