基于QT开发PC端文件加密工具
基于QT开发PC端文件加密工具
1、客户需求
某案子。该方案,通过外挂TF卡实现,本地教育资源的调取使用。按客户需求,把TF卡内的内容进行加密,并在软件中写好解密,确保资源文件只能在教育机中才能正常播放,以防被拷贝复制。
2、涉及的加密文件类型
目前仅支持的加密文件类型:文本(.txt)、图片(.png/.jpg)、视频(.mp4)、音乐(.mp3)
3、开发环境
QT5.12(C++)、Qt程序打包发布方法(使用官方提供的windeployqt工具)
4、设计思路
如图所示,为加密工具的操作界面。操作方法:1、选择待加密文件所在的文件夹;2、选择指定加密文件的新文件夹;3、列出所有待加密的文件;4、一键加密。
软件设计思路:
1、选择待加密文件所在的文件夹
首先是利用QT的槽函数机制,浏览控件都有对应的槽函数。
void MainWindow::on_SelectSourceFilepushButton_3_clicked()
{//获取应用的当前路径,并通过QString类定义的变量保存该路径QString curPath = QCoreApplication::applicationDirPath();//设置选择弹框的标题QString dlaTitle = "选择待加密文件";QString selectedDir = QFileDialog::getExistingDirectory(this, dlaTitle, curPath, QFileDialog::ShowDirsOnly);//通过全局变量保存待加密文件的文件路径SourceFilePath = selectedDir;if(!selectedDir.isEmpty()){//通过comboBox控件显示选择的指定文件夹路径ui->comboBox->addItem(selectedDir);//初始化进度条为0ui->progressBar->setValue(0);}
}
分析:类MainWindow为主界面,成员函数on_SelectSourceFilepushButton_3_clicked,亦为浏览控件的槽函数。
2、选择指定加密文件的新文件夹
void MainWindow::on_SelectTargetFile_pushButton_clicked()
{//获取应用的当前路径,并通过QString类定义的变量保存该路径QString curPath = QCoreApplication::applicationDirPath();QString dlaTitle = "选择目标文件";//选择指定文件夹,并保存该文件夹的路径QString selectedDir = QFileDialog::getExistingDirectory(this, dlaTitle, curPath, QFileDialog::ShowDirsOnly);//通过全局变量来保存指定文件夹的文件路径TargetFilePath = selectedDir;if(!selectedDir.isEmpty()){//通过comboBox_2控件显示选择的指定文件夹路径ui->comboBox_2->addItem(selectedDir);}
}
分析:类MainWindow为主界面,成员函数on_SelectTargetFile_pushButton_clicked,亦为浏览控件的槽函数。
3、列出所有待加密的文件
void MainWindow::on_ListAllFileButton_clicked()
{QString curPath = SourceFilePath; //获取待加密文件的文件路径QStringList fileList; //用字符串列表的类定义对象fileListQString filter;ListWidget TmpListWight; //列表窗口的类定义对象TmpListWightui->listWidget_2->clear(); //清除主界面上的列表窗口totalfiles = 0; //初始化用于记录总待加密文件数的变量file_info_list = TmpListWight.GetFileList(curPath); //根据文件路径,直接获取所有文件的路径信息//循环遍历 file_info_list对象中所有的路径,并获取文件信息fileinfoforeach(QFileInfo fileinfo, file_info_list){filter = fileinfo.suffix(); //获取文件后缀名//过滤文件if( (filter != "jpg") && (filter != "jpeg")&&(filter != "png") && filter != "mp3" && filter != "txt" && filter != "mp4") {continue;}//将每个文件路径添加到列表中fileList.append(fileinfo.absoluteFilePath());//在listWidget_2显示ui->listWidget_2->addItem(fileinfo.absoluteFilePath());}
}
4、一键加密
void MainWindow::on_EncryptionButton_clicked()
{//创建加密文件的线程newThread();
}
void MainWindow::newThread()
{ThreadEncryptionFile *NewThreadFile = new ThreadEncryptionFile;QObject::connect(NewThreadFile,SIGNAL(UpdateProgressBar(double)),this,SLOT(processbar(double)));//启动线程,开始执行工作线程的任务NewThreadFile->start();
}
分析:成员变量默认是界面的子类了,不会再生成一个线程。new出来的话就是在堆中,默认是一个新进程。这里注意用new来创建新线程。connect()函数有且只能在QObject类里面和QObject派生类里面使用,自己新建的类里面(基类不是QObject类和其QObject派生类)使用connect()函数是无效的,编译时会报错。新建工程比如widget,mainwindow,dialog都是QObject的派生类,所以可以直接使用connect()函数,实现信号与槽机制。NewThreadFile->start()启动线程。
重点说下自定义的加密类:
//继承 线程的加密类
class ThreadEncryptionFile :public QThread
{Q_OBJECT
public:bool ReadFile(const QString& SourceFileName, const QString& TargetFileName);bool CopyDirectoryFiles(const QString &fromDir,const QString &toDir);bool getFileCount( const QString& sPath );void Encryption_copy(const QString& SourceFileName, const QString& TargetFileName);void EncryptionTextFile(const QString& SourceFileName, const QString& TargetFileName);void EncryptionMusicFile(const QString& SourceFileName, const QString& TargetFileName);void EncryptionPhotoFile(const QString& SourceFileName, const QString& TargetFileName);void EncryptionMovieFile(const QString& SourceFileName, const QString& TargetFileName);QByteArray FileToByteArray(const QString& SourceFileName);U8 word_encrypt(U8 val, U8 Secretkey);
//信号 用来通知更新 进度条
signals:void UpdateProgressBar(double );
protected:void run();
};
分析:QThread是线程类,是实现多线程操作的核心类,一般从QThread继承定义自己的线程类,本设计就是用的这种方式。在从QThread继承一个自定义类,并重定义虚函数run(),在run()函数里实现线程需要完成的任务,该线程可以通过调用start()开始执行工作线程的任务。
再来看看主界面的类:
class MainWindow : public QMainWindow
{Q_OBJECT
public:MainWindow(QWidget *parent = nullptr);~MainWindow();
private slots:void on_EncryptionButton_clicked();void on_ListAllFileButton_clicked();void on_SelectTargetFile_pushButton_clicked();void on_SelectSourceFilepushButton_3_clicked();void processbar(double index);void newThread();
private:Ui::MainWindow *ui;QProgressBar *progressBar;
public:QFileInfoList file_info_list;
};
分析:主窗口的类,主要是各个控件的槽函数。以及关联进度条,和文件信息列表类。
重点->加密线程中的执行内容:
void ThreadEncryptionFile::run()
{getFileCount(SourceFilePath); //获取待加密文件总数CopyDirectoryFiles(SourceFilePath, TargetFilePath); //拷贝目录文件,同时完成加密工作
}
获取待加密文件总数的方法如下:
bool ThreadEncryptionFile::getFileCount(const QString &sPath)
{QDir dir( sPath ); //目录类实例化对象dirQFileInfoList fileInfoList = dir.entryInfoList(); //文件信息列表类实例化对象fileInfoList,并初始化foreach ( QFileInfo fileInfo, fileInfoList ) {if ( fileInfo.fileName() == "." || fileInfo.fileName() == ".." ) {continue;}totalfiles++; //统计待加密文件总数qDebug() << "totalfile:" << totalfiles;if (fileInfo.isDir()) {if (!getFileCount(fileInfo.filePath()))return false;} //当为目录时,递归的进行}return true;
}
拷贝目录文件,同时完成加密工作如下:
bool ThreadEncryptionFile::CopyDirectoryFiles(const QString &fromDir,const QString &toDir)
{QDir sourceDir(fromDir); //待加密文件所在文件夹QDir targetDir(toDir); //指定文件夹if(!targetDir.exists()) {if(!targetDir.mkdir(targetDir.absolutePath())) {return false;}} //指定文件夹不存在,则创建新文件夹QFileInfoList list = sourceDir.entryInfoList();for(int i = 0; i < list.size(); i++) {QFileInfo fileInfo = list.at(i);if(fileInfo.fileName()=="." || fileInfo.fileName()=="..") {continue;}//如果是目录文件,则创建目录if(fileInfo.isDir()) {if(!CopyDirectoryFiles(fileInfo.filePath(),targetDir.filePath(fileInfo.fileName()))) {return false;}} else {if(targetDir.exists(fileInfo.fileName())) {//有相同的,直接删除targetDir.remove(fileInfo.fileName());}//拷贝完文件后,加密文件Encryption_copy(fileInfo.filePath(), targetDir.filePath(fileInfo.fileName()));}//统计完成文件数量FlishFile++;//通过信号通知界面进度条刷新进度显示emit UpdateProgressBar(FlishFile);qDebug() << "FlishFile:" << FlishFile;}return true;
}
重点中的重点:拷贝完文件&加密文件!!! -> Encryption_copy
void ThreadEncryptionFile::Encryption_copy(const QString& SourceFileName, const QString& TargetFileName)
{QFileInfo TmpFileInfo(SourceFileName);ThreadEncryptionFile EncryFile;//通过文件信息,判断待加密的文件的类型if(!TmpFileInfo.isFile()){return;}QString TmpSuffix = TmpFileInfo.suffix();if(TmpSuffix == "txt"){//待加密文件为文本文件EncryFile.EncryptionTextFile(SourceFileName, TargetFileName);} else if(TmpSuffix == "jpg" || TmpSuffix == "png"){//待加密文件为图片文件EncryFile.EncryptionPhotoFile(SourceFileName, TargetFileName);} else if(TmpSuffix == "mp3") {//待加密文件为音频文件EncryFile.EncryptionMusicFile(SourceFileName, TargetFileName);} else if(TmpSuffix == "mp4") {//待加密文件为视频文件EncryFile.EncryptionMovieFile(SourceFileName, TargetFileName);} else {return;}
}
后面分别描述不同文件类型的加密方式:
文本文件的加密:
/* text [1]所有数据异或^0xD8 [2]增加*** */
void ThreadEncryptionFile::EncryptionTextFile(const QString& SourceFileName, const QString& TargetFileName)
{//先处理目标文件QFile TargetFile(TargetFileName);if(TargetFile.exists()) {//文件存在} else {//文件不存在,直接创建新文件TargetFile.open(QIODevice::ReadWrite);TargetFile.close();}//加密 copy原文件QFile SourceFile(SourceFileName);QByteArray btData;btData = FileToByteArray(SourceFileName);//所有数据异或^0x88for(int i=0; i<btData.size(); i++){btData[i] = word_encrypt(btData[i], g_u8SecretKey);}//增加***btData.prepend("***");if(TargetFile.open(QIODevice::ReadWrite)) {TargetFile.write(btData);TargetFile.close();} else {qDebug() << "read file faile";}
}
图片文件的加密:
void ThreadEncryptionFile::EncryptionPhotoFile(const QString& SourceFileName, const QString& TargetFileName)
{//先处理目标文件QFile TargetFile(TargetFileName);if(TargetFile.exists()) {//文件存在} else {//文件不存在TargetFile.open(QIODevice::ReadWrite);TargetFile.close();}QByteArray btData;QFile SourceFile(SourceFileName);QFileInfo SourceFileInfo(SourceFileName);//通过文件信息,判断待加密的文件的类型if(!SourceFileInfo.isFile()){return;}QString TmpSuffix = SourceFileInfo.suffix();if(TmpSuffix == "jpg"){//增加TOP-TECHbtData = FileToByteArray(SourceFileName);btData.prepend("***");//.jpg[1]遍历前640个字节[3]取反640个字节里面的0xFFD8->0xD8FF(1个就取反一个,有两个标签的话两个都要取反)for(int i=0; i<640; i++){if((btData[i]&0xff) == 0xff&& (btData[i+1]&0xff) == 0xd8){//qDebug() << "0xFFDB->0xD8FF i=" << i;btData[i] = 0xd8;btData[i+1] = 0xff;}}//open target fileif(TargetFile.open(QIODevice::ReadWrite)) {TargetFile.write(btData);TargetFile.close();} else {qDebug() << "read file faile";}} else if (TmpSuffix == "png") {//.png[1]增加***btData = FileToByteArray(SourceFileName);btData.prepend("***");//open target fileif(TargetFile.open(QIODevice::ReadWrite)) {TargetFile.write(btData);TargetFile.close();} else {qDebug() << "read file faile";}}
}
音频文件的加密:
/* music [1]所有数据异或^0x88 [2]增加*** */
void ThreadEncryptionFile::EncryptionMusicFile(const QString& SourceFileName, const QString& TargetFileName)
{//先处理目标文件QFile TargetFile(TargetFileName);if(TargetFile.exists()) {//文件存在} else {//文件不存在TargetFile.open(QIODevice::ReadWrite);TargetFile.close();}QByteArray btData;QFile SourceFile(SourceFileName);btData = FileToByteArray(SourceFileName);//所有数据异或^0x88for(int i=0; i<btData.size(); i++){btData[i] = word_encrypt(btData[i], g_u8SecretKey);}//增加***btData.prepend("***");if(TargetFile.open(QIODevice::ReadWrite)) {TargetFile.write(btData);TargetFile.close();} else {qDebug() << "read file faile";}
}
视频文件的加密:(核心中的重点!!! -> 大文件分段处理)
void ThreadEncryptionFile::EncryptionMovieFile(const QString& SourceFileName, const QString& TargetFileName)
{//先处理目标文件QFile TargetFile(TargetFileName);if(TargetFile.exists()) {//文件存在} else {//文件不存在TargetFile.open(QIODevice::ReadWrite);TargetFile.close();}ReadFile(SourceFileName, TargetFileName);
}
bool ThreadEncryptionFile::ReadFile(const QString& SourceFileName, const QString& TargetFileName)
{QFile SourceFile(SourceFileName);QFile TargetFile(TargetFileName);QByteArray btData;qDebug() << "ThreadEncryptionFile::ReadFile";//打开待加密文件if(!SourceFile.open(QIODevice::ReadWrite)) {qDebug() << "open file faile!";return false;}//打开新建文件if(!TargetFile.open(QIODevice::ReadWrite | QIODevice::Append)) {qDebug() << "open file faile!";return false;}//文件总大小int TotalSize = SourceFile.size();qDebug() << "TmpFile.size:" << SourceFile.size();//将文件分段,每次读取的大小int Count = TotalSize / 1024;//先把头加密内容写到新文件中btData.prepend("***");TargetFile.write(btData);if (Count <= 0) {btData = SourceFile.read(TotalSize);TargetFile.write(btData);} else {for (int i=0; i<Count; i++) {btData = SourceFile.read(1024);TargetFile.write(btData); //读一个段,写一段TotalSize -= 1024;}if (TotalSize != 0) {btData = SourceFile.read(TotalSize);TargetFile.write(btData);}}TargetFile.write(btData);//将加密后的文件写入原文件,得到加密后的文件TargetFile.close();SourceFile.close();return true;
}
最后的重点 -> Qt程序打包发布方法!!!
step 1: 设置工程为Release版本
step 2: 正常编译,生成build-encryption_tool-Desktop_Qt_5_12_9_MinGW_32_bit-Release文件夹
step 3:找到encryption_tool.exe文件,copy到自己新建的demo文件夹中(随便文件夹即可)
step 4: 利用官方提供的windeployqt工具,生成可发布软件(即生成dll,这样除了在自己电脑上可以使用,也可以在别人的电脑上使用)
基于QT开发PC端文件加密工具相关推荐
- 基于Qt开发PC客户端软件
Qt 软件库用来开发PC端软件非常方便,如果有一套系统,即有服务端.移动端及PC端,那么PC端最适合用Qt来开发,设计界面所见即所得.基于C++语言高效灵活.下面基于本人之前开发的一个小软件来说说. ...
- 小悦文件保险箱 - 一款基于DuiLib 库开发的文件加密工具
小悦文件保险箱是一款基于DuiLib 库开发的文件加密工具. 作为学习型编程,所以免费供大家使用.它可以作为加密备忘录使用,也能够为任何文件提供加密保存功能.使用方法也非常简单,先输入密码创建一个自己 ...
- 原神pc端服务器切换工具,基于python3
原神pc端服务器切换工具,基于python3 应我舍友的请求,我用python给他写了一个原神电脑版的服务器切换工具,方便切换服务器. 原理很简单就是用python来进行文件的修改 注意: 此应用为P ...
- 基于Qt开发的网络诊断工具
导语: 项目名称:基于Qt开发的网络诊断工具 开发环境:VS2008 QT版本:4.7 数据读入:用户自行选中的.ini配置文件 功能实现:解析.ini文件,实时检测相关的域名连通性以及DNS解析的结 ...
- QT开发一款MD5校验工具
这是一款基于QT开发的MD5校验工具,在这你可以学习到界面UI的设计方法,以及QT应对字符串的处理方法.以及如何去使用QT进行多线程的开发. 实现后的程序运行截图: MD5.pro工程文件 #---- ...
- PC端RTMP播放工具(EXE,非源码)
PC端RTMP播放工具是一款可以在安卓手机播放rtmp流的工具,基于FFmpeg+openCV开发. 下载地址:PC端RTMP播放工具(EXE,非源码)-直播技术文档类资源-CSDN下载
- 【项目】文件加密工具
项目介绍 本项目是介绍基于Boost大数库实现RSA文件加密工具,RSA体制是一种分组密码,其明文和密文均为 0~n-1 之间的整数,通常n的大小为 1024 位二进制数或 309 位十进制数 ...
- pygame开发PC端微信打飞机游戏
pygame开发PC端微信打飞机游戏 一.项目简介1. 介绍本项目类似曾经火爆的微信打飞机游戏.游戏将使用Python语言开发,主要用到pygame的API.游戏最终将会以python源文件game ...
- 基于qt开发的智能系统:电子相册,监控摄像头模块,音乐播放器,视频播放器,电子时钟
登录模块 源码请移步 //登录验证按钮函数 void MainWindow::on_loginBtn_clicked() {//获得userNameLEd输入框的文本userNameLEd->t ...
最新文章
- gridcontrol值为0时设置为空_XASSET 4.0入门指南
- python 使用sqlite3
- mysql基础表和修理表_MySQL基础知识——创建数据库和表
- 2 Effect Hook
- CPU有个禁区,内核权限也无法进入!
- 三家快递公司涨派费:9月1日起每票上调0.1元
- COSC1076_assignment2_221
- 能力素质有所欠缺_任职资格体系之七:员工能力评价模型
- 年底看机会,欢迎加入Java大数据招聘群!
- confluence权限管理
- 构造可以使n个城市连接的最小生成树—C语言实现
- 如何查看别人的微信公众号的粉丝数
- IllegalArgumentException :argument type mismatch
- android仿ppt,android 仿ppt进入动画效果合集
- js绘制菱形(空心和实心)
- ITU BT 601建议及与ITU BT656 的区别
- ARM嵌入式Linux系统设计与开发
- 2021年登高架设考试技巧及登高架设考试试题
- 《编程之美》一摞烙饼问题探讨
- 酷睿i5 12450h和i7 12700h选哪个好
热门文章
- 每天都有人偷我森林的能量,我写了一个蚂蚁森林自动化收取能量!看你们咋偷!
- vs2013中如何安装OpencvSharp并使用
- 谷歌浏览器:检查更新时出错:无法启动更新检查(错误代码为 4: 0x80070005 -- system level)
- 图像抽象成彩色文字/符号/黑色气泡
- KBEngine(CBE)引擎研究 (一) 启动正确的进程
- 怎么把照片做成电子相册?照片制作视频,简单3步快速拥有炫酷特效!
- 什么是PEAR?(第二篇)
- 请叫我面霸!面试拼多多,从一面到入职,我只用了35天!
- k8s之Deployment详解
- 我的故事:从一段“Hello World“开始