У меня есть приложение пользовательского интерфейса на C++ и QT5.4, я использую CryptoPP 5.6.2 для шифрования файлов. Я столкнулся со следующей проблемой:
При нажатии кнопки «Зашифровать» запускается новый поток на основе это руководство.
// new thread CryptoWorkerThread = new QThread; this->worker = new CryptoWorker(fileName.c_str(), newFileName.c_str(), key, keyLength, iv); this->worker->moveToThread(CryptoWorkerThread); connect(worker, SIGNAL(error(QString)), this, SLOT(errorString(QString))); connect(CryptoWorkerThread, SIGNAL(started()), worker, SLOT(process())); connect(worker, SIGNAL(finished()), CryptoWorkerThread, SLOT(quit())); connect(worker, SIGNAL(finished()), this, SLOT(on_CryptoWorker_finished())); connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater())); connect(CryptoWorkerThread, SIGNAL(finished()), CryptoWorkerThread, SLOT(deleteLater())); CryptoWorkerThread->start();
Я храню указатель на поток и рабочий процесс в классе mainwindow (родитель кнопки шифрования и, следовательно, слот)
Рабочий класс:
class CryptoWorker : public QObject { Q_OBJECT public: CryptoWorker(const char* sourceFileName, const char* destFileName, const byte * key, int keyLength, const byte * iv); ~CryptoWorker(); const char* sourceFileName; const char* destFileName; public slots: void process(); signals: void finished(); void error(QString err); private: // add your variables here const byte* key; const byte* iv; int keyLength; }; CryptoWorker::CryptoWorker(const char* sourceFileName, const char* destFileName, const byte * key, int keyLength, const byte * iv){ this->sourceFileName = sourceFileName; this->destFileName = destFileName; this->key = key; this->keyLength = keyLength; this->iv = iv; } CryptoWorker::~CryptoWorker(){ } void CryptoWorker::process(){ CryptoPP::CBC_Mode<CryptoPP::AES>::Encryption encryptor(key, keyLength, iv); CryptoPP::FileSource(sourceFileName, true, new CryptoPP::StreamTransformationFilter( encryptor, new CryptoPP::FileSink(destFileName), CryptoPP::BlockPaddingSchemeDef::PKCS_PADDING ), true // StreamTransformationFilter ); // FileSource emit finished(); return; }
Теперь, когда поток запущен, и я шифрую файл A в файл B на лету, используя эту функцию:
CryptoPP::FileSource(sourceFileName, true,
new CryptoPP::StreamTransformationFilter(
encryptor,
new CryptoPP::FileSink(destFileName),
CryptoPP::BlockPaddingSchemeDef::PKCS_PADDING
),
true // StreamTransformationFilter
); // FileSource
Но поток зависает до тех пор, пока файл не завершит кодирование и запись, что может занять несколько минут. У меня нет возможности убить тред, так как негде поставить галочку isAlive()
.
Я пытаюсь найти решение, которое позволит мне использовать FileSource, FileSink (скорость по сравнению с fstream или file или qfile потрясающая), а также позволит мне отменить операцию в какой-то момент.
Я решил отслеживать прогресс, добавив еще один поток, который проверяет размер нового создаваемого зашифрованного файла B, но было бы здорово иметь контроль над байтами, которые записываются в данный момент (чтобы я мог проверять isAlive()
и увеличивать счетчики данных ).
На данный момент я застрял и не могу найти решение. Пожалуйста помоги.