当前位置: 首页 > news >正文

qt之QFTP对文件夹(含嵌套文件夹和文件)、文件删除下载功能

一、前言

主要功能如下:

1.实现文件夹的下载和删除,网上很多资料都是单独对某个路径的文件操作的,并不能对文件夹操作

2.实现目标机中含中文名称自动转码,有些系统编码方式不同,下载出来的文件会乱码

3.实现ftp功能保活,在正常使用时ftp如果挂载超过5分钟会自动断开

4.实现ftp复位重连,ftp是官方在qt5舍弃的,因为有bug,登录失败时再次登录就会出现问题,这里也是通过一些方法避免了这个问题,每次登录可重新判断网络和账号密码信息

此资源为qt5.7的代码cpp文件和相关main函数和结构体定义h文件,需要嵌入到自己的程序中修改一下类接口调用部分,并不是一个独立的程序。只要你是真正的软件工程师10000000%能正常使用。

此资源中没有实现的功能如下:

没有做上传功能,因为项目没有使用,用于数据存储设备,定期通过软件导出硬盘下某个总数据的文件夹不同日期的数据,修改起来会很简单,同下载方式差不太多。

没有做目录的进入退出功能,这个功能也很简单,网上也有很多demo

二、环境

windows

qt5.7

下载资源(温馨提示有费用,但是保值)

三、正文

首先请看VCR,哈哈

注意:速度与网络环境有关,网络条件差的当文件量特别多时可能会出现卡顿、延迟等现象

下面附上一些关键的核心代码

1.复位登录重连方法

//连接设备按键
void appdataoutput::on_btnConn_clicked()
{//判断账号密码输入栏是否为空,进行错误提示if(ui->lineEdit_name->text().isEmpty()||ui->lineEdit_passwd->text().isEmpty()){massage_dialog(1,"提示","设备账户或密码不能为空!",1,30);return;}resetFTP();//复位FTPclearControls();//清除信息//判断是否已经登录,如果已经登录了就不需要重复登录if (m_ftp->state() != QFtp::LoggedIn){ui->textEdit->append("------------------------");ui->textEdit->append("正在连接,请确保网络链路正常连通...");m_ftp->connectToHost(sIP, 21);//设置IP和端口m_ftp->login(ui->lineEdit_name->text(),ui->lineEdit_passwd->text());//登录账号密码}else if(m_ftp->state() != QFtp::Connecting)massage_dialog(1,"提示","已连接,未登录!",1,30);elsemassage_dialog(1,"提示","已登录,无需重复登录!\n如有异常请退出重新进入!",1,30);
}
//复位FTP
void appdataoutput::resetFTP()
{m_ftp->state();m_ftp->abort();m_ftp->deleteLater();m_ftp = nullptr;m_ftp = new QFtp(this);connect(m_ftp, SIGNAL(dataTransferProgress(qint64, qint64)),SLOT(S_upDateProgress(qint64, qint64))); // 进度条显示connect(m_ftp, SIGNAL(commandStarted(int)), this,SLOT(ftpCommandStarted(int)));    //命令启动connect(m_ftp, SIGNAL(commandFinished(int, bool)),SLOT(ftpcommandFinish(int, bool))); //命令完成connect(m_ftp, SIGNAL(stateChanged(int)), this,SLOT(ftpStateChanged(int)));//状态改变connect(m_ftp, SIGNAL(listInfo(const QUrlInfo&)), this,SLOT(addToList(const QUrlInfo&))); // 添加文件项connect(m_ftp, SIGNAL(done(bool)), this, SLOT(ftpDone(bool)));//完成
}

就是每次登录把之前的ftp关闭掉,重新启动

2.保活方法

    ///timer定时器初始化 ftp保活QTimer *time1=new QTimer(this);time1->start(120*1000);//2分钟执行一次,不发送ftp命令 5分钟自动断开connect(time1,&QTimer::timeout,[=](){if(m_FTPconnectflag==2){//判断是否连接成功QByteArray keepfile=QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss zzz").toLatin1();m_ftp->put(keepfile,toSpecialEncoding(m_keeppath));//向目标设备写入数据,定期保持ftp活跃,避免自动关闭qDebug()<<"发送程序保活"<<QString(keepfile);}});

在初始化时创建定时器,定时判断是否连接成功,连接成功状态下定期向ftp中上传一个文件。

m_FTPconnectflag变量跟随ftp连接状态动态改变

3.编码中英文切换

//转码 从目标机器编码转window中文
QString ftpDownloadDir::fromSpecialEncoding(const QString& inputStr)
{
#ifdef FTP_to_windowQTextCodec* codec = QTextCodec::codecForName("GBK");//UTF-8return codec->toUnicode(inputStr.toLatin1());
#elsereturn inputStr.toLatin1();//linux A40i连接需要使用此方式
#endif
}
//转码 从window中文转目标机器编码
QString ftpDownloadDir::toSpecialEncoding(const QString& inputStr)
{
#ifdef FTP_to_windowQTextCodec* codec = QTextCodec::codecForName("GBK");//UTF-8return QString::fromLatin1(codec->fromUnicode(inputStr));
#elsereturn QString::fromLatin1(QTextCodec::codecForName("UTF-8")->fromUnicode(inputStr));//linux A40i连接需要使用此方式
#endif
}

在目标机中有的是gbk编码,有的是utf8编码,在window下面是utf8编码,需要把ftp中读取的文件夹或文件含中文编码的转换为window能够识别的,在进入目标机子目录使用cd命令时需要将中文在转回机器编码

4.文件夹遍历下载,ftp操作函数

/FTP状态槽函数/
//进度条
void appdataoutput::S_upDateProgress(qint64 _used, qint64 _total)
{auto percent = (qreal)_used / _total * 100;
//    qDebug()<<QString("appdataoutput进度:%1%").arg(QString::number(percent,'f',2));
//    ui->progressBar->setValue(percent);
}
//命令启动
void appdataoutput::ftpCommandStarted(int tem)
{
//    qDebug()<<"ftpCommandStarted"<<m_ftp->currentCommand();if (m_ftp->currentCommand() == QFtp::ConnectToHost) {ui->textEdit->append("【start】连接目标设备...");}if (m_ftp->currentCommand() == QFtp::Login) {ui->textEdit->append("【start】登录目标设备...");}if (m_ftp->currentCommand() == QFtp::Get) {ui->textEdit->append("【start】下载程序...");}if (m_ftp->currentCommand() == QFtp::Put) {
//        ui->textEdit->append("【start】上传程序...");qDebug()<<"【start】上传程序...";}if (m_ftp->currentCommand() == QFtp::Remove) {ui->textEdit->append("【start】删除程序...");}if (m_ftp->currentCommand() == QFtp::Close) {ui->textEdit->append("【start】关闭设备连接...");}
}
//ftp 连接状态更改
void appdataoutput::ftpStateChanged(int state)
{if (state == QFtp::Unconnected) {if(m_FTPconnectflag==0)//FTP连接登录状态  0:未登录 1:连接成功 2:登录成功ui->textEdit->append("【change】未连接目标设备,请检查网络是否正常连接,请检查目标设备FTP端口是否开启");else if(m_FTPconnectflag==1)//FTP连接登录状态  0:未登录 1:连接成功 2:登录成功ui->textEdit->append("【change】未登录目标设备,请检查目标设备账号密码是否正确");else{ui->textEdit->append("【change】与目标设备连接断开");m_FTPconnectflag=0;//FTP连接登录状态  0:未登录 1:连接成功 2:登录成功}ui->btnConn->setEnabled(true);//使能连接按键ui->lineEdit_name->setEnabled(true);//使能用户名输入栏ui->lineEdit_passwd->setEnabled(true);//使能密码输入栏}if (state == QFtp::HostLookup) {ui->textEdit->append("【change】正在查找目标设备");}if (state == QFtp::Connecting) {ui->textEdit->append("【change】正在连接目标设备");}if (state == QFtp::Connected) {ui->textEdit->append("【change】已经连接目标设备");}if (state == QFtp::LoggedIn) {ui->textEdit->append("【change】已登录目标设备");}if (state == QFtp::Closing) {ui->textEdit->append("【change】连接正在关闭");}
}
//命令完成
void appdataoutput::ftpcommandFinish(int tmp, bool error)
{// 防止编译器对未使用变量的警告Q_UNUSED(tmp);//登录状态if (m_ftp->currentCommand() == QFtp::ConnectToHost) {if (error) {ui->textEdit->append(QString("【finish】连接目标设备出现错误:%1").arg(m_ftp->errorString()));}else {m_FTPconnectflag=1;//FTP连接登录状态  0:未登录 1:连接成功 2:登录成功ui->textEdit->append("【finish】连接目标设备成功");}}else if (m_ftp->currentCommand() == QFtp::Login) {if (error) {ui->textEdit->append(QString("【finish】登录出现错误:%1").arg(m_ftp->errorString()));}else {m_FTPconnectflag=2;//FTP连接登录状态  0:未登录 1:连接成功 2:登录成功ui->textEdit->append("【finish】登录目标设备成功,可下载导出历史数据文件");ui->btnConn->setEnabled(false);//失能登录按键ui->lineEdit_name->setEnabled(false);//失能用户名输入栏ui->lineEdit_passwd->setEnabled(false);//失能密码输入栏m_ftp->cd(toSpecialEncoding(m_historypath));//进入到数据存储路径,否则在默认路径root文件夹下。进入路径后执行m_ftp->list()会多次进入addToList,所以cd函数禁止放入在refreshed中}}else if (m_ftp->currentCommand() == QFtp::Close){ui->textEdit->append("【finish】已经关闭目标设备连接");}//功能状态else if (m_ftp->currentCommand() == QFtp::Get){if (error) {ui->textEdit->append(QString("【finish】下载出现错误:%1").arg(m_ftp->errorString()));}else{ui->textEdit->append("【finish】已经完成下载");}
//        refreshed();}else if (m_ftp->currentCommand() == QFtp::Put){if (error) {
//            ui->textEdit->append(QString("【finish】上传出现错误:%1").arg(m_ftp->errorString()));qDebug()<<QString("【finish】上传出现错误:%1").arg(m_ftp->errorString());m_ftp->abort();}else{
//            ui->textEdit->append("【finish】已经完成上传");qDebug()<<"【finish】已经完成上传";}}else if (m_ftp->currentCommand() == QFtp::Rename){ui->textEdit->append("【finish】文件重命名成功");
//        refreshed();}else if (m_ftp->currentCommand() == QFtp::Mkdir){ui->textEdit->append("【finish】新建文件夹成功");
//        refreshed();}else if (m_ftp->currentCommand() == QFtp::Remove){ui->textEdit->append("【finish】程序文件删除成功");
//        refreshed();}else if (m_ftp->currentCommand() == QFtp::Rmdir){ui->textEdit->append("【finish】文件夹删除成功");
//        refreshed();}else if (m_ftp->currentCommand() == QFtp::Cd){if (error) {ui->textEdit->append(QString("【finish】进入目录出现错误:%1").arg(m_ftp->errorString()));}else{ui->textEdit->append("【finish】进入目录成功");refreshed();}}else if (m_ftp->currentCommand() == QFtp::List){if (error) {qDebug()<<QString("【finish】刷新目录出现错误:%1").arg(m_ftp->errorString());}else{qDebug()<<QString("【finish】刷新目录成功");if(m_FTPconnectflag==2){//判断ftp是否正常连接,断开时不执行内部内容,只有连接时才执行里面内容tableWidget_refuse(ui->tableWidget);//刷新表格//获取整个历史数据目录大小if(m_sata_status)//硬盘状态正常则获取硬盘数据总大小download_ftpdir(1,0,m_satapath,m_satahistorydir,"");//查询根目录文件大小}}}
}
//完成ftp功能
void appdataoutput::ftpDone(bool error)
{if(error){qDebug()<<QString("【Done】FTP操作出现错误:%1").arg(m_ftp->errorString());}else{qDebug()<<QString("【Done】FTP操作完成");}
}
//刷新槽函数
void appdataoutput::addToList(const QUrlInfo& urlInfo)
{QString fileSize; // 用于存储文件大小,根据文件大小字节,设置文件在树列表的单位if (urlInfo.size() >= 0 && urlInfo.size() < 1024){fileSize = QString::number(urlInfo.size()) + "Byte";}else if (urlInfo.size() >= 1024 && urlInfo.size() < 1024 * 1024){fileSize = QString::number(urlInfo.size() / 1024.0, 'f', 2) + "KB";}else if (urlInfo.size() >= 1024 * 1024 && urlInfo.size() < 1024 * 1024 * 1024){fileSize = QString::number(urlInfo.size() / 1024 / 1024.0, 'f', 2) + "MB";}else if (urlInfo.size() >= 1024 * 1024 * 1024){fileSize = QString::number(urlInfo.size() / 1024 / 1024 / 1024.0, 'f', 2) + "GB";}QString dir=urlInfo.isDir() ? "文件夹" : "文件";QString name=fromSpecialEncoding(urlInfo.name());//转码,中文需要根据系统区分编码qDebug()<<dir<<name<<fileSize<<urlInfo.lastModified().addSecs(3600*8).toString("yyyy-MM-dd hh:mm:ss")<<urlInfo.owner()<<urlInfo.group();//赋值逐项查询的列表信息HistoryList listdata;listdata.name=fromSpecialEncoding(urlInfo.name());//转码,将目标机的url编码转换为能够识别中文的编码
#ifdef FTP_to_windowlistdata.time=urlInfo.lastModified();
#elselistdata.time=urlInfo.lastModified().addSecs(3600*8);
#endiflistdata.isdir=urlInfo.isDir();//是否为文件夹,true文件夹,false文件listdata.numdir=0;//文件夹数量(若是文件夹后面会更新)listdata.numfile=1;//文件数量(若是文件夹后面会更新)listdata.allbyte=urlInfo.size();//文件夹总大小 字节(若是文件夹后面会更新)listdata.timenew=listdata.time;//最新数据文件时间(若是文件夹后面会更新)if(dir=="文件"){//文件,直接显示查询的大小listdata.size=fileSize;m_satadata.append(listdata);//数据缓存,等待list刷新完毕之后进入done函数刷新表格}else if((dir=="文件夹") && (name!=".") && (name!= "..")){//判断是文件夹,计算大小 //目录.或..不刷新显示if(m_sata_status){//硬盘状态正常则获取硬盘数据总大小download_ftpdir(1,0,m_historypath,listdata.name,"");//查询各个根目录下子文件大小listdata.size="计算中...";}elselistdata.size="硬盘错误";m_satadata.append(listdata);//数据缓存,等待list刷新完毕之后进入done函数刷新表格}if(listdata.name=="loop.sh"){m_sata_status=false;//当路径搜索到loop.sh说明没有进入到硬盘路径,进入到了默认的root路径ui->label_path->setText("数据存储路径:"+m_historypath+"  !!!路径异常,经检查硬盘是否未安装或损坏!!!");ui->textEdit->append("【刷新】硬盘识别失败,未进入到硬盘路径,请检查硬盘状态!");}}

5.最核心的子ftp操作函数,在父类ftp中要下载某个文件或文件夹,将路径传入到此函数中,会创建新的类,开启新的ftp去执行某个文件或文件夹下面所有的文件下载,删除等

//下载路径下的文件夹(暂时只能下载文件夹内容。不能单独下载文件)
//flag:    0:空闲 1:下载单个文件夹   2:下载2个及以上文件夹
//mode:    0:获取指定目录文件夹大小,不下载  1:下载指定目录文件夹到本机  2:删除指定目录文件夹  3:下载指定文件 4:删除指定文件
//path_MBJ 目标机源文件下载根目录   //固定不变
//dir_MBJ  要下载的源文件夹名称    //固定不变
//path_BJ  客户端保存路径         //固定不变
void appdataoutput::download_ftpdir(char flag,char mode,QString path_MBJ,QString dir_MBJ,QString path_BJ)
{m_FTPdownloadflag=flag;//FTP下载状态  0:空闲  1:下载单个文件  2:下载2个及以上文件夹FtpItem dirdown;dirdown.ftpmode=mode;//ftp工作模式 0:获取指定目录文件夹大小,不下载  1:下载指定目录文件夹到本机dirdown.srcRootDir=path_MBJ;//目标机源文件下载根目录   //固定不变dirdown.srcDirName=dir_MBJ;//要下载的源文件夹名称     //固定不变dirdown.saveRootDir=path_BJ;//客户端保存路径         //固定不变QUrl ftpurl;//ftp的登录信息,用于给独立的下载文件功能类提供登录信息ftpurl.setHost(sIP);ftpurl.setPort(21);ftpurl.setUserName(ui->lineEdit_name->text());ftpurl.setPassword(ui->lineEdit_passwd->text());dirdown.url=ftpurl;//ftp登录信息ftpDownloadDir *aaa=new ftpDownloadDir(dirdown/*,this*/);aaa->setAttribute(Qt::WA_DeleteOnClose);//若是关闭界面,则彻底释放资源aaa->downloadDir();//开始下载//下载进度,下载操作才会返回connect(aaa,&ftpDownloadDir::updateprogress,[=](qint64 bytesSent, qint64 bytesTotal){//刷新实时返回的子文件项目进度ui->progressBar_now->setRange(0,bytesTotal);ui->progressBar_now->setValue(bytesSent);auto percent = (qreal)bytesSent / bytesTotal * 100;ui->progressBar_now->setFormat(QString("%1%").arg(QString::number(percent,'f',0)));});connect(aaa,&ftpDownloadDir::updateprogress1,[=](int filenum){//刷新当前下载项目的进度  刷新全部下载项目的进度//计算刷新当前下载项目的进度tableWidget_progress(ui->tableWidget,dir_MBJ,filenum);//更新表格文件大小内容//计算刷新全部下载项目的进度if(m_FTPdownloadflag==1){//总体进度为单个文件夹int number=filenum*100/m_download_filenum;ui->progressBar_all->setFormat(QString("%1%").arg(number));//设置显示ui->progressBar_all->setValue(number);//设置总体进度}else if(m_FTPdownloadflag==2){//总体进度为多个文件int overnum=0;for(int i=0;i<m_satadata.size();i++){//继续遍历寻找待下载文件夹if(m_satadata[i].downflag==3){overnum+=m_satadata[i].numfile;}}int number=(overnum+filenum)*100/m_download_filenum;ui->progressBar_all->setFormat(QString("%1%").arg(number));//设置显示ui->progressBar_all->setValue(number);//设置总体进度}});//下载完毕,下载操作才会返回connect(aaa,&ftpDownloadDir::downloaddone,[=](FtpItemout res){qDebug()<<"downloaddone下载完毕:"<<res.allsizie<<QString::number(res.allbyte)<<res.faildirpathlist;if(res.faildirpathlist.size()>0){ui->listWidget->setVisible(true);//设置下载错误列表显示ui->listWidget->addItems(res.faildirpathlist);}QString printdown=QString("【下载】文件/夹(%1),内部文件夹%2个,文件%3个,成功%4个,失败%5个,总大小%6(%7字节)").arg(dir_MBJ).arg(QString::number(res.numdir)).arg(QString::number(res.numfile)).arg(QString::number(res.iSeccessNum)).arg(QString::number(res.iFailNum)).arg(res.allsizie).arg(QString::number(res.allbyte));ui->textEdit->append(printdown);if(m_FTPdownloadflag==1){//下载单个文件m_FTPdownloadflag=0;//FTP下载状态  0:空闲  1:下载单个文件  2:下载2个及以上文件夹massage_dialog(1,"提示",QString("已下载(%1)数据文件").arg(dir_MBJ),1,30);}else if(m_FTPdownloadflag==2){//下载2个及以上文件夹QStringList dirnamelist;dirnamelist.clear();for(int i=0;i<m_satadata.size();i++)dirnamelist.append(m_satadata[i].name);int numid=dirnamelist.indexOf(dir_MBJ);//获取下载完毕的序号m_satadata[numid].downflag=3;//下载队列 0:不下载  1:等待下载  2:下载中  3:下载完毕QCheckBox *m_checkbox = ui->tableWidget->findChild<QCheckBox*>("t_checkBox_"+QString::number(numid));m_checkbox->setChecked(false);//下载完后取消选择for(int i=0;i<m_satadata.size();i++){//继续遍历寻找待下载文件夹if(m_satadata[i].downflag==1){//有等待下载的m_satadata[i].downflag=2;//下载队列 0:不下载  1:等待下载  2:下载中  3:下载完毕qDebug()<<"下载数据"<<m_satadata[i].name<<",下载到"+m_downpath;if(m_satadata[i].isdir)download_ftpdir(2,1,m_historypath,m_satadata[i].name,m_downpath);//下载文件夹else download_ftpdir(2,3,m_historypath,m_satadata[i].name,m_downpath);//下载文件break;//跳出循环,只下载第一个符合条件的,后续还有的话就等待下载完毕后判断状态循环下载}if(i==(m_satadata.size()-1)){//判断最后一个数据仍然没退出循环,则代表最后一个下载数据完毕qDebug()<<"全部文件下载完毕!";m_FTPdownloadflag=0;//FTP下载状态  0:空闲  1:下载单个文件  2:下载2个及以上文件夹QString allfilename;for(int j=0;j<m_satadata.size();j++){if(m_satadata[j].downflag==3){//获取所有下载完毕的文件名allfilename.append(m_satadata[j].name+",");}}allfilename=allfilename.mid(0,allfilename.size()-1);//去掉最后一个 逗号for(int j=0;j<m_satadata.size();j++)//清除下载队列m_satadata[j].downflag=0;//下载队列 0:不下载  1:等待下载  2:下载中  3:下载完毕massage_dialog(1,"提示",QString("已下载(%1)数据文件").arg(allfilename),1,30);}}}writeLog(printdown);//日志记录});//下载错误,下载操作才会返回connect(aaa,&ftpDownloadDir::downloadfailed,[=](){qDebug()<<"downloadfailed下载错误:";ui->textEdit->append(QString("【下载】错误,连接断开"));m_FTPdownloadflag=0;//FTP下载状态  0:空闲  1:下载单个文件  2:下载2个及以上文件夹writeLog("【下载】错误,连接断开");//日志记录});//读取文件大小,读取操作才会返回connect(aaa,&ftpDownloadDir::downloadsize,[=](FtpItemout res){qDebug()<<"downloadsize读取大小:"<<res.allsizie<<QString::number(res.allbyte);if(dir_MBJ==m_satahistorydir){//判断是获取整个硬盘历史数据文件大小ui->progressBar_disk->setFormat(QString("%1(%2Byte)").arg(res.allsizie).arg(res.allbyte));ui->textEdit->append(QString("【刷新】硬盘数据大小:%1(%2Byte)").arg(res.allsizie).arg(res.allbyte));}else{tableWidget_update(ui->tableWidget,dir_MBJ,res);//更新表格文件大小内容}m_FTPdownloadflag=0;//FTP下载状态  0:空闲  1:下载单个文件  2:下载2个及以上文件夹});//文件夹删除,删除操作才会返回connect(aaa,&ftpDownloadDir::deletedir,[=](){qDebug()<<"deletedir删除文件:"<<dir_MBJ;ui->textEdit->append(QString("【删除】文件/夹(%1)").arg(dir_MBJ));massage_dialog(1,"提示",QString("已删除(%1)数据文件").arg(dir_MBJ),1,30);m_FTPdownloadflag=0;//FTP下载状态  0:空闲  1:下载单个文件  2:下载2个及以上文件夹refreshed();//刷新writeLog(QString("【删除】文件/夹(%1)").arg(dir_MBJ));//日志记录});
}

这个函数不同的mode执行不同的功能,对应的信号槽返回也不同,有下载成功的,有下载失败的,有进度条的,有删除的,有获取大小的。

可以说appdataoutput就是主菜单,ftpDownloadDir才是真正的功能操作。

四、结语

觉得有用的话就去下载吧

相关文章:

qt之QFTP对文件夹(含嵌套文件夹和文件)、文件删除下载功能

一、前言 主要功能如下&#xff1a; 1.实现文件夹的下载和删除&#xff0c;网上很多资料都是单独对某个路径的文件操作的&#xff0c;并不能对文件夹操作 2.实现目标机中含中文名称自动转码&#xff0c;有些系统编码方式不同&#xff0c;下载出来的文件会乱码 3.实现ftp功能…...

为何数据库推荐将IPv4地址存储为32位整数而非字符串?

目录 一、IPv4地址在数据库中的存储方式&#xff1f; 二、IPv4地址的存储方式比较 &#xff08;一&#xff09;字符串存储 vs 整数存储 &#xff08;二&#xff09;IPv4地址"192.168.1.8"说明 三、数据库推荐32位整数存储方式原理 四、存储方式对系统性能的影响…...

Mybatis框架之责任链模式 (Chain of Responsibility Pattern)

在 MyBatis 框架中&#xff0c;责任链模式 (Chain of Responsibility Pattern) 被广泛应用于多个功能模块中&#xff0c;例如 插件拦截器、SQL 执行流程中的拦截器链、动态 SQL 的解析与处理等。这种设计模式为 MyBatis 提供了高度的扩展性和灵活性&#xff0c;使其能够轻松应对…...

C++ Stack和Queue---单向守护与无尽等待:数据结构的诗意表达

公主请阅 容器适配器容器适配器的特点 栈和队列的模拟实现deque的介绍1. 内存开销较高2.随机访问性能略低于 vector3. 与指针或迭代器的兼容性r4. 不适合用于需要频繁中间插入和删除的场景5. 在特定平台上的实现不一致6. 缺乏shrink_to_fit支持总结 题目 priority_queue 优先级…...

深入理解Java包装类与泛型的应用

今天我将带领大家进入Java包装类和泛型应用的学习。 我的个人主页 我的Java-数据结构专栏 &#xff1a;Java-数据结构&#xff0c;希望能帮助到大家。 一、Java包装类基础 二、Java泛型基础 三、Java包装类与泛型的结合 四、Java泛型进阶 五、Java包装类与泛型实战 一、Ja…...

【机器学习chp4】特征工程

推荐文章1&#xff0c;其中详细分析了为什么L1正则化可以实现特征选择&#xff08;特征剔除&#xff09; 【王木头 L1、L2正则化】三个角度理解L1、L2正则化的本质-CSDN博客 推荐文章2&#xff0c;里面详细分析了奇异值分解 【线性代数】矩阵变换-CSDN博客 本文遗留问题&#…...

LeetCode螺旋矩阵

快一个月没刷题了&#xff0c;最近工作有些忙&#xff0c;今天闲下来两小时&#xff0c;刷一道 题目描述 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,2,3],[4…...

第十五届蓝桥杯JAVA的B组题目详情解析

(第一个填空太简单&#xff0c;就不写了,根本不用代码&#xff0c;直接excel计算) 目录 蓝桥杯第二个填空&#xff0c;类斐波那契循环数 蓝桥杯JAVA.b组第三题 -分布式队列(模拟) 食堂(蓝桥杯D题) ​编辑 星际旅行(Floyd佛洛依德) 其余的有点变态&#xff0c;感觉学了好像…...

在几分钟内将数据从 Oracle 迁移到 ClickHouse

ClickHouse 是一个开源的面向列的数据库管理系统。它在实时数据处理方面的出色性能显着增强了数据分析和业务洞察力。将数据从 Oracle 迁移到 ClickHouse 可以释放数据在决策中的力量&#xff0c;这是单独使用 Oracle 无法实现的。 本教程介绍如何使用 BladePipe 将数据从 Orac…...

ASP.NET MVC宠物商城系统

该系统采用B/S架构&#xff0c;使用C#编程语言进行开发&#xff0c;以ASP.NET MVC框架为基础&#xff0c;以Visual Studio 2019为开发工具&#xff0c;数据库采用SQL Server进行保存数据。系统主要功能包括登录注册、宠物展示、个人中心、我的订单、购物车、用户管理、宠物类别…...

完整http服务器

目录 背景目标描述技术特点开发环境WWW客户端浏览发展史服务端http发展史http分层概览 背景 http协议被广泛使用&#xff0c;从移动端&#xff0c;pc浏览器&#xff0c;http无疑是打开互联网应用窗口的重要协议&#xff0c;http在网络应用层中的地位不可撼动&#xff0c;是能…...

【专题】2024AIGC创新应用洞察报告汇总PDF洞察(附原数据表)

原文链接&#xff1a;https://tecdat.cn/?p38310 在科技日新月异的今天&#xff0c;人工智能领域正以前所未有的速度发展&#xff0c;AIGC&#xff08;人工智能生成内容&#xff09;成为其中最耀眼的明珠。从其应用场景的不断拓展&#xff0c;到对各行业的深刻变革&#xff0…...

形态学图像处理(Morphological Image Processing)

形态学图像处理(Morphological Image Processing) 前言 ‍ 本博客为个人总结数字图像处理一课所写&#xff0c;并给出适当的扩展和相应的demo。 写博客跟做 checkpoint​ 很像&#xff0c;毕竟个人还不能达到那种信手拈来的境界&#xff0c;忘了就是从零开始训练&#xff0…...

【IDER、PyCharm】免费AI编程工具完整教程:ChatGPT Free - Support Key call AI GPT-o1 Claude3.5

文章目录 CodeMoss 简介CodeMoss 的模型集成如何安装和配置 CodeMossIDER 插件安装步骤 CodeMoss 的实战使用AI 问答功能代码优化与解释优化这段代码解释这段代码 文件上传与对话联网查询与 GPT 助手联网查询GPT 助手 提升开发效率的最佳实践结语更多文献 CodeMoss 简介 CodeM…...

C++11的一些实用特性

1.统一的列表初始化 在C98中&#xff0c;标准允许使用花括号{}对数组或者结构体元素进行统一的列表初始值设定。 //统一的列表初始化 struct Date {int year;int month;int day; };void test1() {Date d1 { 2024,11,14 };int array1[] { 1, 2, 3, 4, 5 };int array2[5] { …...

23种设计模式-观察者(Observer)设计模式

文章目录 一.什么是观察者模式&#xff1f;二.观察者模式的结构三.观察者模式的应用场景四.观察者模式的优缺点五.观察者模式的实现&#xff08;C示例&#xff09;六.观察者模式的实现&#xff08;JAVA示例&#xff09;七.代码解释八.总结 类图&#xff1a; 观察者设计模式类图…...

【CUDA】Branch Divergence and Unrolling Loop

目录 一、避免分支发散 1.1 并行规约问题 1.2 并行规约中的发散 二、UNrolling Loops 一、避免分支发散 控制流有时依赖于 thread 索引。同一个warp中&#xff0c;一个条件分支可能导致性能很差。通过重新组织数据获取模式可以减少或避免 warp divergence。具体问题查看下…...

深度学习:卷积神经网络的计算复杂度,顺序操作,最大路径长度

卷积层的计算复杂度 在深度学习中&#xff0c;卷积层的计算复杂度主要取决于卷积核的大小、输入和输出的通道数量、以及输入序列的长度。具体来说&#xff0c;卷积层的计算复杂度可以通过以下几个因素来计算&#xff1a; 卷积核大小 k&#xff1a;卷积核的大小决定了每次卷积操…...

springboot 配置文件中 multipart.max-file-size 各个版本的写法

由于springboot具有几个版本&#xff0c;不同版本对于文件上传最大限制的配置也有所不同。 所以要注意springboot本身的版本&#xff0c;不然会一直报错 在springboot1.3版本中&#xff1a; multipart.maxFileSize在springboot1.4与springboot1.5版本中&#xff1a; spring…...

linux 中mysql查看慢日志

1、到mysql容器&#xff0c;先登录到数据库&#xff0c;查看是否开启 mysql -h 127.0.0.1 -uroot -p SHOW VARIABLES LIKE slow_query_log; 2、如果没有开启&#xff0c;需要先开启 set global slow_query_log ON; 3、查看慢日志文件 SHOW VARIABLES LIKE slow_query_log…...

单片机的基本组成与工作原理

单片机&#xff08;Microcontroller Unit, MCU&#xff09;是一种将计算机的主要部分集成在一个芯片上的小型计算机系统。它通常包括中央处理器&#xff08;CPU&#xff09;、存储器&#xff08;Memory&#xff09;、输入输出接口&#xff08;I/O Ports&#xff09;、定时器/计…...

智慧隧道和智慧交通

通过引入先进的物联网技术&#xff0c;将各种硬件设备如传感器、摄像头、控制系统等有效地连接并管理起来&#xff0c;以实现道路安全和交通流畅的目标。这些设备将能够实时监控和控制隧道内的各种设备和系统&#xff0c;从而提高道路安全、提升驾驶体验并降低管理成本。 在这个…...

List、Set、Map详解和区别

在 Java 中&#xff0c;List、Set、Map是常用的集合类型&#xff0c;它们各自具有不同的特点和用途&#xff0c;以下是对它们的详细介绍及区别分析&#xff1a; List&#xff08;列表&#xff09; 特点&#xff1a; 有序性&#xff1a;List中的元素是有序的&#xff0c;即元素…...

界面控件DevExpress WinForms v24.2新功能预览 - 支持.NET 9

DevExpress WinForms 拥有180组件和UI库&#xff0c;能为Windows Forms平台创建具有影响力的业务解决方案。DevExpress WinForms能完美构建流畅、美观且易于使用的应用程序&#xff0c;无论是Office风格的界面&#xff0c;还是分析处理大批量的业务数据&#xff0c;它都能轻松胜…...

Postman之pm.test断言操作

Postman之pm.test断言操作 1.断言方法2.连接符3.条件判断符 用于验证请求的响应数据是否符合预期 1.断言方法 pm.test()&#xff1a;定义一个测试函数&#xff0c;接受两个参数&#xff0c;一个字符串参数用来描述该测试&#xff0c;一个返回True/False的函数 语法格式&#…...

对数几率回归

对数几率回归简介 对数几率回归&#xff08;Logistic Regression&#xff09;是一种用于解决分类问题的经典统计模型&#xff0c;其核心思想是利用逻辑函数&#xff08;Sigmoid函数&#xff09;将线性回归模型的输出值映射到概率范围 [0, 1]&#xff0c;从而实现分类预测。对数…...

docker 配置同宿主机共同网段的IP 同时通过通网段的另一个电脑实现远程连接docker

docker配置网络 #宿主机执行命令 ifconfig 查询对应的主机ip 子网掩码 网关地址 #[网卡名称]&#xff1a;inet[主机IP] netmask[子网掩码] broadcast[网关地址]这里需要重点关注&#xff1a;eno1[网卡名称]以及【192.168.31.225】网关地址 在宿主机执行docker命令创建一个虚拟…...

4-7-1.C# 数据容器 - LinkedList(LinkedList 的定义、LinkedList 结点的遍历、LinkedList 的常用方法)

LinkedList 概述 LinkedList<T> 通过节点&#xff08;Node&#xff09;来存储数据&#xff0c;每个节点包含数据和指向下一个节点的引用 LinkedList<T> 存储的元素是可重复的 LinkedList<T> 支持泛型&#xff0c;可以指定存储的元素的类型 LinkedList<…...

「三」体验HarmonyOS端云一体化开发模板——使用DevEco Studio直接创建端云一体化工程

关于作者 白晓明 宁夏图尔科技有限公司董事长兼CEO、坚果派联合创始人 华为HDE、润和软件HiHope社区专家、鸿蒙KOL、仓颉KOL 华为开发者学堂/51CTO学堂/CSDN学堂认证讲师 开放原子开源基金会2023开源贡献之星 「目录」 「一」HarmonyOS端云一体化概要 「二」体验HarmonyOS端云一…...

确保以管理员权限运行 Visual Studio 开发者命令提示符

文章目录 解决方法&#xff1a;1. 以管理员身份运行命令提示符2. 改变目录权限3. 改变项目目录位置4. 检查文件系统权限 总结&#xff1a; ********************************************************************** ** Visual Studio 2022 Developer Command Prompt v17.12.0 …...

网站建设沛宣/曲靖seo建站

优点和使用场景SQL Server 内存中列存储索引通过使用基于列的数据存储和基于列的查询处理来存储和管理数据。 列存储索引适合于主要执行大容量加载和只读查询的数据仓库工作负荷。 与传统面向行的存储方式相比&#xff0c;使用列存储索引存档可最多提高 10 倍查询性能&#xff…...

中山网站制作套餐/品牌宣传策略

转自 http://blog.csdn.net/zhengzhb/article/details/7187278 在java以及其他的面向对象设计模式中&#xff0c;类与类之间主要有6种关系&#xff0c;他们分别是&#xff1a;依赖、关联、聚合、组合、继承、实现。他们的耦合度依次增强。 1. 依赖&#xff08;Dependence&…...

网站虚拟视频主持人/厉害的seo顾问

https://blog.csdn.net/joellj/article/details/81746701...

造价员可以做兼职的网站/如何自创网站

据媒体报道&#xff0c;北京电子商务总交易额超4千亿&#xff0c;年均增长约45%&#xff0c;电子商务企业数量占全国总量的9%&#xff0c;其中B2C领域前十家企业中有六家总部设在北京。北京有望成为中国电子商务企业的聚集地。随着电子商务市场的勃兴&#xff0c;越来越多的企业…...

思源黑体 wordpress/百度外包公司有哪些

交互问答 №.005本篇文章的问题挺有意思&#xff0c;虽然是一个页面中无关紧要的模式&#xff0c;但却是典型的反模式设计&#xff0c;各位可以简单读读。读者提问&#xff1a;社区论坛类产品&#xff0c;天涯、虎扑与百度贴吧的帖子评论页有一个设计差异。天涯、虎扑在帖子评论…...

免费做流程图的网站/温州网站建设

导入表是PE文件中一个重要的表项&#xff0c;负责声明从其他的库中调入函数。一般代表着这个PE文件使用了哪些其他库的函数。首先我们先了解下几个名词&#xff1a;PE文件&#xff1a;PE结构的文件&#xff0c;一般为可执行程序&#xff0c;.exe、.dll、.sys、.vxd、.ocx、.com…...