首頁 > 後端開發 > C++ > 主體

如何中斷 Qt 中的檔案複製和重新命名操作?

Susan Sarandon
發布: 2024-11-13 15:33:02
原創
931 人瀏覽過

How can I interrupt file copy and rename operations in Qt?

中斷檔案複製與重新命名操作

在需要傳輸大檔案並且使用者需要能夠取消操作的情況下, Qt 提供的預設copy() 和rename() 方法可能會受到限制。挑戰在於如何在不引入顯著效能開銷或使用者挫折感的情況下中斷這些進程。

查詢 Qt 中的中斷支援

在研究 QFile 文件時,很明顯 Qt不提供用於中斷 copy() 或 rename() 操作的內建機制。因此,有必要考慮自訂實作策略來滿足此要求。

複製中斷的自訂實作

要建立非阻塞複製助手,一種選擇是實作專用執行緒或利用主執行緒。在任何一種情況下,都需要分段複製,即使用緩衝區以區塊的形式傳輸資料。透過使用緩衝區,可以追蹤操作進度並適應用戶取消請求。

實作自訂複製助理的核心步驟可以描述如下:

  1. 建立一個QObject派生類別來處理複製操作。
  2. 初始化來源路徑、目標路徑、緩衝區大小、進度和清理的屬性
  3. 定義一個begin() 槽來啟動複製過程,其中包括開啟來源檔案和目標檔案以及分配數據傳輸緩衝區。
  4. 實作一個 step() 槽,利用 QMetaObject::invokeMethod() 和 Qt::QueuedConnection,它允許定期處理使用者事件。在此槽中:

    • 檢查複製是否未取消。
    • 使用原始檔案和目標檔案以區塊的形式讀寫資料。
    • 依位置與檔案大小的比值。
    • 遞歸呼叫step()槽,直到整個檔案被複製或取消。
  5. 定義一個 cancel() 槽,允許使用者中斷複製操作並在必要時刪除目標檔案。
  6. 利用訊號通知相關方有關進度變更和完成 (done())。

範例實作

以下程式碼片段提供了複製助理類別的範例實作:

class CopyHelper : public QObject {
    Q_OBJECT
    Q_PROPERTY(qreal progress READ progress WRITE setProgress NOTIFY progressChanged)
public:
    CopyHelper(QString sPath, QString dPath, quint64 bSize = 1024 * 1024) :
        isCancelled(false), bufferSize(bSize), prog(0.0), source(sPath), destination(dPath), position(0) { }
    ~CopyHelper() { free(buff); }

    qreal progress() const { return prog; }
    void setProgress(qreal p) {
        if (p != prog) {
            prog = p;
            emit progressChanged();
        }
    }

public slots:
    void begin() {
        if (!source.open(QIODevice::ReadOnly)) {
            qDebug() << "could not open source, aborting";
            emit done();
            return;
        }
        fileSize = source.size();
        if (!destination.open(QIODevice::WriteOnly)) {
            qDebug() << "could not open destination, aborting";
            // maybe check for overwriting and ask to proceed
            emit done();
            return;
        }
        if (!destination.resize(fileSize)) {
            qDebug() << "could not resize, aborting";
            emit done();
            return;
        }
        buff = (char*)malloc(bufferSize);
        if (!buff) {
            qDebug() << "could not allocate buffer, aborting";
            emit done();
            return;
        }
        QMetaObject::invokeMethod(this, "step", Qt::QueuedConnection);
        //timer.start();
    }
    void step() {
        if (!isCancelled) {
            if (position < fileSize) {
                quint64 chunk = fileSize - position;
                quint64 l = chunk > bufferSize ? bufferSize : chunk;
                source.read(buff, l);
                destination.write(buff, l);
                position += l;
                source.seek(position);
                destination.seek(position);
                setProgress((qreal)position / fileSize);
                //std::this_thread::sleep_for(std::chrono::milliseconds(100)); // for testing
                QMetaObject::invokeMethod(this, "step", Qt::QueuedConnection);
            } else {
                //qDebug() << timer.elapsed();
                emit done();
                return;
            }
        } else {
            if (!destination.remove()) qDebug() << "delete failed";
            emit done();
        }
    }
    void cancel() { isCancelled = true; }

signals:
    void progressChanged();
    void done();

private:
    bool isCancelled;
    quint64 bufferSize;
    qreal prog;
    QFile source, destination;
    quint64 fileSize, position;
    char * buff;
    //QElapsedTimer timer;
};
登入後複製

結論

透過實作自訂複製助理或使用提供的範例,可以建立可以被使用者中斷的非阻塞檔案複製操作。這種方法可以實現響應靈敏且用戶友好的文件傳輸,解決因無法取消的冗長操作而造成的挫敗感。

以上是如何中斷 Qt 中的檔案複製和重新命名操作?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板