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

Qt案例 使用QFtpServerLib开源库实现Qt软件搭建FTP服务器,使用QFTP模块访问FTP服务器

本以为搭建和访问FTP服务器的功能已经是被淘汰的技术了,只会在学习新技术的时候才会了解学习学习,WinFrom版本,和windows Api版本访问FTP服务器的功能示例也都写过。没想到这次会在项目中再次遇到,
这里记录下使用Qt开源库QFtpServerLib搭建FTP服务器,使用旧的QFTP模块代码访问搭建好的FTP服务器功能的示例和部分问题的解决方法。

目录导读

    • 使用QFtpServerLib库搭建FTP服务器
    • 使用QFTP 模块访问FTP服务器
      • 1.解决QFtp::list()方法获取不到文件列表的问题
      • 2.解决QFtp中文乱码,上传包含中文名称的文件会失败的问题

使用QFtpServerLib库搭建FTP服务器

在Windows 系统环境中FTP服务器可以通过IIS搭建,但是有些部分阉割的系统是没有IIS服务的,只能通过在QT软件中搭建FTP服务,保证在软件能运行的时候,FTP服务器也能启动,这种需求自己写绝对够呛,还好在GitHub找到一个现成的三方库.
sashoalm/QFtpServer
在这里插入图片描述
项目运行效果:
在这里插入图片描述

这个库基本的FTP服务都已经实现完毕了,搭建的FTP服务器甚至启动不需要管理员权限,不需要关闭防火墙,完美的解决了局域网数据交互的问题。
上面项目示例中是通过生成静态的QFtpServerLib库调用,
后面我直接改成了.Pri调用,添加到实际项目代码中编译.

  • 创建 QFtpServerLib.pri 文件引用
QT       += network
# INCLUDEPATH += $$[QT_INSTALL_HEADERS]
# TARGET = QFtpServerLib
# TEMPLATE = lib
# DEFINES += QFTPSERVERLIB_LIBRARY
# 设置Utf-8格式编码
# unix {
#     target.path = /usr/lib
#     INSTALLS += target
# }#如果电脑环境上有多个mscv2017/2019/2022等多个版本的编译器,那么需要这一句,用于屏蔽多个vs版本造成的编译异常
QMAKE_PROJECT_DEPTH = 0INCLUDEPATH += $$PWD
SOURCES += \$$PWD/dataconnection.cpp \$$PWD/ftpcommand.cpp \$$PWD/ftpcontrolconnection.cpp \$$PWD/ftplistcommand.cpp \$$PWD/ftpretrcommand.cpp \$$PWD/ftpserver.cpp \$$PWD/ftpstorcommand.cpp \$$PWD/sslserver.cppHEADERS +=\$$PWD/dataconnection.h \$$PWD/ftpcommand.h \$$PWD/ftpcontrolconnection.h \$$PWD/ftplistcommand.h \$$PWD/ftpretrcommand.h \$$PWD/ftpserver.h \$$PWD/ftpstorcommand.h \$$PWD/sslserver.hRESOURCES += \$$PWD/certificates.qrc

直接移除了 qftpserverlib_global.h文件和FtpServer类中的QFTPSERVERLIBSHARED_EXPORT 声明,再将文件添加到.Pri头文件中就行了。
再调整下界面,修改下布局,再添加个FTP服务器启动状态判断,
就能轻松实现如下图示效果:
在这里插入图片描述

  • 创建 FtpServer 实例代码示例:
void FrmFtpServerSetting::StartServerBy(bool bol)
{if(bol){//! 启动服务器if(server!=nullptr){server->stopServer();delete server;server=nullptr;}QString userName="";QString password="";if (!ui->checkBox_Anonymous->isChecked()) {userName = ui->lineEdit_User->text();password = ui->lineEdit_PassWord->text();}delete server;server = new FtpServer(this, ui->lineEdit_RootPath->text(), ui->lineEdit_Port->text().toInt(), userName,password, ui->checkBox_ReadOnly->isChecked(), ui->checkBox_OnlyOneIpAllowed->isChecked());connect(server, SIGNAL(newPeerIp(QString)), SLOT(PeerIpChanged(QString)));if (server->isListening()) {EnabledWidget(true);// ui->statusBar->showMessage("Listening at " + FtpServer::lanIp());QString Address="";if(!ui->checkBox_Anonymous->isChecked())Address=QString("ftp://%1:%2@%3:%4/").arg(ui->lineEdit_User->text()).arg(ui->lineEdit_PassWord->text()).arg(FtpServer::lanIp()).arg(ui->lineEdit_Port->text().trimmed());elseAddress=QString("ftp://@%1:%2/").arg(FtpServer::lanIp()).arg(ui->lineEdit_Port->text().trimmed());ui->label_FtpAddress->setText(QString("<html><head/><body><p>访问地址:<a href=\"%1\" style=\" text-decoration: underline; color:#003e92;\">""%2</a></p></body></html>").arg(Address,Address));ui->pushButton->setIcon(QApplication::style()->standardIcon((enum QStyle::StandardPixmap)48));ui->pushButton->setText("关闭FTP服务");LoadMessInfo("已启动FTP服务!请访问:<br><a href=\"###\" style=\" text-decoration: underline; color:#003e92;\">"+Address+"</a>");SaveToSetting();} else {delete server;server=nullptr;ui->label_FtpAddress->setText("<html><head/><body><p>访问地址:<a href=\"ftp://username:password@ip:port/\" style=\" text-decoration: underline; color:#003e92;\">ftp://username:password@ip:port/</a></p></body></html>");LoadMessInfo("未能创建监听!请尝试重启FTP服务!!");ui->pushButton->setIcon(QApplication::style()->standardIcon((enum QStyle::StandardPixmap)49));ui->pushButton->setText("启动FTP服务");EnabledWidget(false);}}else{//! 启动服务器if(server!=nullptr){server->stopServer();delete server;server=nullptr;}//! 关闭服务器ui->label_FtpAddress->setText("<html><head/><body><p>访问地址:<a href=\"ftp://username:password@ip:port/\" style=\" text-decoration: underline; color:#003e92;\">ftp://username:password@ip:port/</a></p></body></html>");LoadMessInfo("已关闭FTP服务,请重启FTP服务以获取访问地址!!!");ui->pushButton->setIcon(QApplication::style()->standardIcon((enum QStyle::StandardPixmap)49));ui->pushButton->setText("启动FTP服务");EnabledWidget(false);}}

QFtpServerLib库 示例代码中已经实现了相关功能!代码简单,照抄就行了;
其他功能参考:
z1908144712/QtFtpServer也是通过基于QFtpServerLib库 实现的。


使用QFTP 模块访问FTP服务器

在Qt5中,官方已经移除了QFtp类,可以从Qt4的源代码中获取并重新编译,
这里同样是在网上找到已经编译好的Qt5.1.0版本的开源库
https://github.com/qt/qtftp
在这里插入图片描述
这个示例中的功能过于繁琐了,还需要生成QFTP模块,再引用到项目中,
实际上直接把
qurlinfo.h
qurlinfo.cpp
qftp.h
qftp.cpp
四个文件包含到项目文件中,添加QT += network就能直接使用。
注意将qftp.h文件中的
#include <QtFtp/qurlinfo.h>改为#include "qurlinfo.h"
除此之外这个库还需要解决两个问题:

  • 1.解决QFtp::list()方法获取不到文件列表的问题

在使用QFtp库的时候,我测试了半天愣是没有获取到文件列表,一度怀疑前面搭建的FTP服务器是不是没搭建好,但是通过文件资源管理器和360游览器都能正常访问FTP服务器并获取文件列表,
在网上找了半天,都说是int QFTP::list(const QString &dir = QString());的解析文件目录有问题,
但是又都没说具体的问题在哪,于是只能苦逼的看qftp.cpp源代码。
通过不断地qDebug()调试,找到
621行 bool QFtpDTP::parseDir(const QByteArray &buffer, const QString &userName, QUrlInfo *info)
解析不了传进来的类 Unix 风格的字符串
drwxrwxrwx unknown unknown 0 Apr 22 16:56 PropertyRedact\r\n
-rw-rw-rw- unknown unknown 115300 Apr 22 16:50 PropertyRedact.zip\r\n
drwxrwxrwx unknown unknown 0 Apr 22 16:58 Ftp_Server\r\n
drwxrwxrwx unknown unknown 0 Apr 07 17:19 build-PropertyRedact-Desktop_Qt_5_13_1_MSVC2017_64bit-Release\r\n
QFTP有设置Unix style FTP servers的解析格式

    // Unix style FTP serversQRegExp unixPattern(QLatin1String("^([\\-dl])([a-zA-Z\\-]{9,9})\\s+\\d+\\s+(\\S*)\\s+""(\\S*)\\s+(\\d+)\\s+(\\S+\\s+\\S+\\s+\\S+)\\s+(\\S.*)"));int num=unixPattern.indexIn(bufferStr);//qDebug()<<"indexIn: "<<num;if (num == 0) {_q_parseUnixDir(unixPattern.capturedTexts(), userName, info);return true;}

但是跟上面传进来的字符就多少有点不匹配了,
通过分析正则表达式可知:

分段匹配目标示例匹配值
^([-dl])文件类型(首字符):-(文件)、d(目录)、l(符号链接)d(目录)
([a-zA-Z-]{9,9})文件权限(9个字符):rwxrwxrwx 或类似组合(-表示无权限)rwxrwxrwx
\s+\d+\s+硬链接数量(通常为数字,目录至少为 2)
(\S*)\s+文件所有者(非空白字符,可能为空)unknown
(\S*)\s+文件所属组(非空白字符,可能为空)unknown
(\d+)\s+文件大小(字节数,目录通常为 0)0
(\S+\s+\S+\s+\S+)修改时间(通常为 月 日 时间 或 月 日 年)Apr 22 16:56
\s+(\S.*)文件名(可能包含空格,直到行尾)PropertyRedact\r\n

在用户组前面缺了个硬链接数量 数字类型导致内容不匹配,
重新修改正则表达示字符串:以适应上述字符串

    //! 追加修改-修改字符串匹配QRegExp unixPattern2(QLatin1String("^([\\-dl])([a-zA-Z\\-]{9,9})\\s+(\\S+)\\s+(\\S+)\\s+""(\\d+)\\s+(\\S+\\s+\\S+\\s+\\S+)\\s+(\\S.*)"));//qDebug()<<"unixPattern2 : "<<unixPattern2.indexIn(bufferStr);if (unixPattern2.indexIn(bufferStr) == 0) {_q_parseUnixDir(unixPattern2.capturedTexts(), userName, info);return true;}

这下就正常获取到文件列表了

  • 2.解决QFtp中文乱码,上传包含中文名称的文件会失败的问题

QFtp.cpp中都是使用的QString::fromLatin1或者.toLatin1()来处理字符串,这就导致了在链接Ftp服务器后中文乱码,甚至上传中文名称文件都失败的问题,
这时只需要将
QString::fromLatin1 ->改成: QString::fromUtf8
.toLatin1() ->改成: .toUtf8()
头文件添加
#if defined(_MSC_VER) && (_MSC_VER >= 1600)
# pragma execution_character_set("utf-8")
#endif
就能解决中文乱码的问题,
再参考ftpwindow.h文件的示例,就能了解FTP库的调用,
实现如下图示功能:
在这里插入图片描述
其中:

  • 创建FTP客户端监听示例:
    connectOrDisconnect();#ifndef QT_NO_CURSORsetCursor(Qt::WaitCursor);
#endif//qDebug()<<"on_connectButton_clicked-- >";ftp = new QFtp(this);connect(ftp, SIGNAL(commandFinished(int,bool)),this, SLOT(ftpCommandFinished(int,bool)));connect(ftp, SIGNAL(listInfo(QUrlInfo)),this, SLOT(addToList(QUrlInfo)));connect(ftp, SIGNAL(dataTransferProgress(qint64, qint64)),this, SLOT(dataTransferProgress(qint64, qint64)));///主动模式ftp->setTransferMode(QFtp::Active);ui->fileList->clear();currentPath.clear();isDirectory.clear();//![2]QUrl url(ui->ftpServerLineEdit->text());if (!url.isValid() || url.scheme().toLower() != QLatin1String("ftp")) {ftp->connectToHost(ui->ftpServerLineEdit->text(), 21);} else {ftp->connectToHost(url.host(), url.port(21));if (!url.userName().isEmpty())ftp->login(QUrl::fromPercentEncoding(url.userName().toUtf8()), url.password());elseftp->login();if (!url.path().isEmpty())ftp->cd(url.path());}//![2]//!ui->fileList->setEnabled(true);ui->connectButton->setEnabled(false);ui->connectButton->setText(tr("Disconnect"));ui->statusLabel->setText(tr("Connecting to FTP server %1...").arg(ui->ftpServerLineEdit->text()));

值得一提的是 qtftp在上传文件时,需要先关闭文件再上传,否则会上传失败,

  • 上传文件示例:
 //! 上传文件
QString fileName="";
fileName=QFileDialog::getOpenFileName(this,"提示",".","");
if(fileName.isEmpty()|| !QFileInfo::exists(fileName))return;upfile= new QFile(fileName);
if (!upfile->open(QFile::ReadWrite)) {QMessageBox::information(this, tr("FTP"),tr("Unable to open the file %1: %2.").arg(fileName).arg(upfile->errorString()));delete upfile;return;
}
//!必须先关闭文件 否则后面无法打开文件上传
upfile->close();
ui->progressBar->setMaximum(100);
ui->progressBar->setValue(0);
ui->progressBar->show();
QFileInfo info(fileName);
// ftp->put(upfile->readAll(),info.fileName());
ftp->put(upfile,info.fileName());

这里展示了部分功能,更多内容建议查看QFtp.hftpwindow.h文件内容。

相关文章:

Qt案例 使用QFtpServerLib开源库实现Qt软件搭建FTP服务器,使用QFTP模块访问FTP服务器

本以为搭建和访问FTP服务器的功能已经是被淘汰的技术了&#xff0c;只会在学习新技术的时候才会了解学习学习&#xff0c;WinFrom版本&#xff0c;和windows Api版本访问FTP服务器的功能示例也都写过。没想到这次会在项目中再次遇到&#xff0c; 这里记录下使用Qt开源库QFtpSer…...

图像后处理记录

图像后处理记录 ocr后处理记录 opencv裁剪 编译命令 cmake -S . -B build-x64 -DBUILD_LIST"core,imgproc,imgcodecs,highgui" -DBUILD_SHARED_LIBSOFF -DBUILD_opencv_appsOFF -DBUILD_opencv_jsOFF -DBUILD_ANDROID_PROJECTSOFF -DBUILD_ANDROID_EXAMPLESOFF -…...

解决element中的el-anchor链接被作为路由跳转导致页面404

解决element中的el-anchor链接被作为路由跳转导致页面404 问题&#xff1a; 在使用elementPlus时&#xff0c;el-anchor-link中的href被识别为路由进行跳转&#xff0c;导致不能正常跳转到锚点&#xff0c;且页面显示404。 解决&#xff1a;自定义方法解决 <!--添加hand…...

Mapreduce中maven打包

MapReduce是一个分布式运算程序的编程框架&#xff0c;是用户开发“基于Hadoop的数据分析应用”的核心框架。 MapReduce核心功能是将用户编写的业务逻辑代码和自带默认组件整合成一个完整的分布式运算程序&#xff08;例如&#xff1a;jar包&#xff09;&#xff0c;并发运行在…...

C++初阶——string的使用(下)

C初阶——string的使用&#xff08;下&#xff09; 一、string类对象的容量操作 对于string的容量操作&#xff0c;我们可以通过顺序表来理解&#xff0c;顺序表是通过动态数组来实现的&#xff0c;在数据结构专栏的第一篇就是顺序表的详细讲解&#xff0c;链接如下&#xff…...

AIGC vs 人类创作者:是竞争还是协作?

AIGC vs 人类创作者&#xff1a;是竞争还是协作&#xff1f; 随着人工智能技术的飞速发展&#xff0c;特别是生成式AI&#xff08;AIGC, AI-Generated Content&#xff09;的崛起&#xff0c;越来越多的领域开始出现AI的身影。从文本创作、图像生成到音乐制作&#xff0c;AIGC…...

Stable Baselines3 结合 gym 训练 CartPole 倒立摆

视频讲解&#xff1a; Stable Baselines3 结合 gym 训练 CartPole 倒立摆 今天介绍下stable_baselines3和gym&#xff0c;可以方便实现DL的实现&#xff0c;应用在机械臂catch、reach等场景 测试代码仓库&#xff1a;https://github.com/LitchiCheng/DRL-learning.git https:…...

ctfshow web8

前言 学习内容&#xff1a;简单的盲注脚本的书写 web8 这个题目题目手动注入很麻烦 主要是他过滤了 union 空格和 过滤了union的解决方法 1、使用盲注(报错注入和盲注) 2、使用时间盲注 3、堆叠注入 盲注脚本的书写 首先他是有注入点的 然后熟悉requests包的使用 …...

Linux程序地址空间

目录 研究背景 程序地址空间回顾 来段代码感受一下 进程地址空间 Linux2.6内核进程调度队列 一个CPU拥有一个runqueue 优先级 活跃队列&#xff08;只出不进&#xff09; 过期队列&#xff08;只进不出&#xff09; active指针和expired指针 总结 研究背景 Linux内核版本&#…...

破茧成蝶:阿里云应用服务器让传统 J2EE 应用无缝升级 AI 原生时代

丝滑升级拥抱大模型&#xff1a;详解AI时代的应用智能化升级路径 破茧成蝶&#xff1a;阿里云应用服务器让传统 J2EE 应用无缝升级AI原生时代 ——十年代码无需重写&#xff0c;三步开启智能化跃迁 作者&#xff1a;孤弋、孚阳 序幕&#xff1a;一场跨越 20 年的技术对话 在杭…...

游戏引擎学习第240天:将渲染器移至第三层

这节又枯燥又无聊简直了 回顾并为今天的内容做铺垫 昨天我们说到&#xff0c;想对渲染器和平台层的集成方式做一些修改。我们之前简单讲了一下修改的目的&#xff1a;我们希望游戏本身不再直接调用 OpenGL 的渲染代码&#xff0c;而是只生成一组渲染指令缓冲区&#xff0c;然…...

2025.04.23华为机考第三题-300分

📌 点击直达笔试专栏 👉《大厂笔试突围》 💻 春秋招笔试突围在线OJ 👉 笔试突围OJ 03. 时空旅行者的最优路径 问题描述 A先生是一名时空旅行者,他可以在不同的时空点之间穿梭。每次从一个时空点跳跃到另一个时空点需要消耗一个时间单位。在每个时空点,都有一些特…...

Kafka 保证多分区的全局顺序性的设计方案和具体实现

Kafka 本身无法直接保证多分区的全局顺序性&#xff0c;因为分区设计旨在并行处理以提升吞吐量。 要实现多分区的顺序性&#xff0c;可尝试通过以下方法在系统层面或业务逻辑上解决&#xff1a; 一、方案设计 单一分区路由&#xff08;还是将消息发送到同一分区&#xff09;&a…...

数据结构初阶:二叉树(四)

概述&#xff1a;本篇博客主要介绍链式结构二叉树的实现。 目录 1.实现链式结构二叉树 1.1 二叉树的头文件&#xff08;tree.h&#xff09; 1.2 创建二叉树 1.3 前中后序遍历 1.3.1 遍历规则 1.3.1.1 前序遍历代码实现 1.3.1.2 中序遍历代码实现 1.3.1.3 后序遍历代…...

华为开发岗暑期实习笔试(2025年4月16日)

刷题小记&#xff1a; 第一题怀疑测试样例不完整&#xff0c;贪心法不应该能够解决该题。第二题使用0-1BFS解决单源最短路径的问题&#xff0c;往往搭配双端队列实现。第三题是运用动态规划解决最大不重叠子区间个数的问题&#xff0c;难点在于满足3重判断规则&#xff0c;所需…...

第一篇:Django简介

第一篇&#xff1a;Django简介 文章目录 第一篇&#xff1a;Django简介一、纯手写一个简易版的web框架1、软件开发架构2、HTTP协议3、简易的socket服务端4、wsgiref模块5、动静态网页6、后端获取当前时间展示到html页面上7、字典数据传给html文件8、数据从数据库中获取的展示到…...

2025年渗透测试面试题总结-拷打题库13(题目+回答)

网络安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 2025年渗透测试面试题总结-拷打题库13 一、GitHub等三方敏感信息泄漏防御 二、业务逻辑漏洞技术规避 …...

(09)Vue脚手架的使用(Vite、vue-cli、create-vue)

本系列教程目录&#xff1a;Vue3Element Plus全套学习笔记-目录大纲 文章目录 第3章 Vue脚手架3.1 vite3.3.1 Vite使用1&#xff09;创建Vite项目2&#xff09;Vite项目打包 3.1.2 组件化开发3.1.4 Vite工程运行原理1&#xff09;分析main.js2&#xff09;自定义根组件 3.2 vue…...

Unity 将Excel表格中的数据导入到Mysql数据表中

1.Mysql数据表users如下&#xff1a; 2.即将导入的Excel表格如下&#xff1a; 3.代码如下&#xff1a; using System; using System.Data; using System.IO; using Excel; using MySql.Data.MySqlClient; using UnityEngine; using UnityEditor;public class ImportExcel {// …...

【QT】信号与槽中多个按钮(pushbutton)共用一个槽函数的两种实现方式

两种方法的对比 方法1&#xff1a;sender() 优点&#xff1a;代码简洁&#xff0c;无需额外参数 缺点&#xff1a;依赖运行时类型转换&#xff0c;安全性较低 适用场景&#xff1a;简单场景&#xff0c;少量按钮 方法2&#xff1a;Lambda (推荐) 优点&#xff1a;安全直观&…...

Python----深度学习(神经网络的过拟合解决方案)

一、正则化 1.1、正则化 正则化是一种用于控制模型复杂度的技术。它通过在损失函数中添加额外的项&#xff08;正则 化项&#xff09;来降低模型的复杂度&#xff0c;以防止过拟合。 在机器学习中&#xff0c;模型的目标是在训练数据上获得较好的拟合效果。然而&#xff0c;过…...

【金仓数据库征文】从 HTAP 到 AI 加速,KingbaseES 的未来之路

国产数据库早已实现 “可替代”&#xff0c;但要真正与国际头部厂商掰手腕&#xff0c;必须在 HTAP&#xff08;Hybrid‑Transaction/Analytical Processing&#xff09;与 AI 加速 两条技术赛道上实现跨越。KingbaseES 自 V8R3 调整为多进程架构后&#xff0c;历经 V8R6、KSOn…...

创建第一个Spring Boot项目

什么是Spring Boot 随着Spring的快速发展&#xff0c;项目中的XML文件越来越多&#xff0c;繁琐的配置以及&#xff0c;整合第三方框架的配置问题&#xff0c;导致大大增加了开发和部署的效率&#xff0c;使开发者无法专心于业务的开发。Spring Boot就相当于使Spring框架的脚手…...

Java—— 正则表达式 练习

需求&#xff1a; 请编写正则表达式验证用户输入的手机号码是否满足要求。 请编写正则表达式验证用户输入的邮箱号是否满足要求。 请编写正则表达式验证用户输入的电话号码是否满足要求。 验证手机号码 13112345678 13712345667 13945679027 139456790271 验证座机电话号码 02…...

Linux[指令与权限]

Linux指令与权限 Linux环境中,打包文件有多种 tar (打包/解包) 指令 tar -czvf 文件要打包到的位置 文件(打包并压缩到) tar -xzvf 文件(在当前目录下解压) tar选项 -c创建压缩文件 -z使用gzip属性压缩 -v展现压缩过程 -f后面使用新建文档名 -x不要新建,解压 -C 文件…...

MySQL数据库精研之旅第十期:打造高效联合查询的实战宝典

专栏&#xff1a;MySQL数据库成长记 个人主页&#xff1a;手握风云 目录 一、简介 1.1. 为什么要使用联合查询 1.2. 多表联合查询时的计算 1.3. 示例 二、内连接 2.1. 语法 2.2. 示例 三、外连接 4.1. 语法 4.2. 示例 一、简介 1.1. 为什么要使用联合查询 一次查询需…...

【Redis】集合类型Set 常用命令详解

1. sadd - 添加 语法&#xff1a;sadd key value > sadd testset A 1 > sadd testset B 1 > sadd testset C 1 > sadd testset C # set的值不能重复 0 > smembers set1 # 查询指定set的所有值&#xff0c;乱序 1) "B" 2) "A" 3) "C&qu…...

React 5 种组件提取思路与实践

在开发时,经常遇到一些高度重复但略有差异的 UI 模式,此时我们当然会把组件提取出去,但是组件提取的方式有很多,怎么根据不同场景选取合适的方式呢?尤其时在复杂的业务场景中,组件提取的思路影响着着代码的可维护性、可读性以及扩展性。本文将以一个[详情]组件为例,探讨…...

第十五届蓝桥杯 2024 C/C++组 合法密码

目录 题目&#xff1a; 题目描述&#xff1a; 题目链接&#xff1a; 思路&#xff1a; substr函数&#xff1a; 思路详解&#xff1a; 代码&#xff1a; 代码详解; 题目&#xff1a; 题目描述&#xff1a; 题目链接&#xff1a; P10906 [蓝桥杯 2024 国 B] 合法密码 -…...

云原生时代的双轮驱动

在当今数字化浪潮汹涌澎湃的时代&#xff0c;企业 IT 主管、CIO、CTO 们肩负着引领企业乘风破浪、实现数字化转型的重任。而主数据平台与数据中台&#xff0c;宛如企业数字化征程中的双引擎&#xff0c;为企业发展注入强劲动力。 一、主数据与数据中台&#xff1a;企业数据世界…...

GD32F407单片机开发入门(六)定时器TIMER详解及实战含源码

文章目录 一.概要二.通用定时器内部结构1.时基单元2.时钟源3.输入捕获4.输出比较 三.通用定时器内部特色四.TIME定时器1ms中断例程五.工程源代码下载六.小结 一.概要 定时器就是计数器&#xff0c;应用在我们生活的方方面面&#xff0c;比如有闹钟、计时器等。在GD32F407VET6定…...

时序数据库 TDengine 助力石油石化业务, 平滑接替 Oracle 数据库

小T导读&#xff1a;胜软科技在石油石化行业中选择使用 TDengine 处理时序数据&#xff0c;不仅显著降低了运维数据库的成本&#xff0c;也大幅减少了存储空间的占用&#xff0c;实现了从原有的 40 多套 Oracle 数据库向仅 9 套 TDengine集群的精简替换。在迁移过程中&#xff…...

【问题解决】本机navicat连接云服务器mysql

一般情况下&#xff0c;当你使用navicat等工具连接云服务器会因为mysql的安全机制&#xff0c;导致无法连接root用户&#xff0c;但是在测试环境中&#xff0c;不考虑安全性的前提条件下&#xff0c;可以通过修改MySQL的配置文件来连接云服务器mysql的root用户。 选择数据库&am…...

STM32F407 的通用定时器与串口配置深度解析

在 STM32F407 芯片的开发过程中&#xff0c;通用定时器和串口的配置与使用是极为关键的技能点。本文将结合提供的代码示例&#xff0c;深入剖析这两个模块的配置流程、工作原理以及实际应用&#xff0c;助力开发者更好地掌握相关技术。 一、通用定时器 &#xff08;一&#x…...

深入探究Linux项目自动化构建工具:make与Makefile

目录 引言 一、make与Makefile概述 1.1 背景 1.2 理解 二、make工作原理 2.1 查找Makefile 2.2 确定目标文件 2.3 处理文件依赖 三、Makefile实例分析 3.1 简单C程序示例 3.2 项目清理机制 四、结合行缓冲区概念的有趣现象 五、结语 引言 在Linux软件开发的世界里…...

【Hive入门】Hive基础操作与SQL语法:DDL操作全面指南

目录 1 Hive DDL操作概述 2 数据库操作全流程 2.1 创建数据库 2.2 查看数据库 2.3 使用数据库 2.4 修改数据库 2.5 删除数据库 3 表操作全流程 3.1 创建表 3.2 查看表信息 3.3 修改表 3.4 删除表 4 分区与分桶操作 4.1 分区操作流程 4.2 分桶操作 5 最佳实践与…...

STM32F103 “BluePill” 上的 DMA 原理与实践

摘要:本文深入浅出地介绍什么是 DMA(直接存储器访问),它的核心原理、硬件架构,以及在 STM32F103(BluePill)上常见的几种使用场景(ADC、UART、内存拷贝等)。通过对比 CPU 轮询、中断、DMA 三种方式的数据搬运效率,结合寄存器级和 HAL 库示例代码,并附带性能测试与优化…...

软考软件设计师30天备考指南

文章目录 一、考情分析&#xff08;一&#xff09;综合知识&#xff08;二&#xff09;案例分析 二、30天学习规划&#xff08;一&#xff09;第1 - 5天&#xff1a;基础夯实&#xff08;二&#xff09;第6 - 10天&#xff1a;核心知识突破&#xff08;三&#xff09;第11 - 15…...

比较:AWS VPC peering与 AWS Transit Gateway

简述: VPC 对等连接和 Transit Gateway 用于连接多个 VPC。VPC 对等连接提供全网状架构,而 Transit Gateway 提供中心辐射型架构。Transit Gateway 提供大规模 VPC 连接,并简化了 VPC 间通信管理,相比 VPC 对等连接,支持大量 VPC 的 VPC 间通信管理。 VPC 对等连接 AWS V…...

【AI大模型】MCP:AI应用的“超级扩展坞”

一、什么是MCP MCP&#xff08;Model Context Protocol&#xff0c;模型上下文协议&#xff09;是一种新兴的开放协议&#xff0c;于2024年11月由Anthropic公司&#xff08;Claude的开发者&#xff09;开源。它的核心目标是建立一个类似USB-C的标准化协议&#xff0c;统一AI模…...

线程封装

目录 makefile Thread.hpp main.cc 以面向对象的方式造轮子 #ifndef _THREAD_HPP__ // 如果没有定义过 _THREAD_HPP__ #define _THREAD_HPP__ // 则定义 _THREAD_HPP__// 这里是头文件的实际内容&#xff08;类、函数声明等&#xff09;#endif // 结束条件…...

【Java后端】MyBatis 与 MyBatis-Plus 如何防止 SQL 注入?从原理到实战

在日常开发中&#xff0c;SQL 注入是一种常见但危害巨大的安全漏洞。如果你正在使用 MyBatis 或 MyBatis-Plus 进行数据库操作&#xff0c;这篇文章将带你系统了解&#xff1a;这两个框架是如何防止 SQL 注入的&#xff0c;我们又该如何写出安全的代码。 什么是 SQL 注入&#…...

智能穿戴的终极形态会是AR眼镜吗?

清晨的地铁里&#xff0c;戴着普通眼镜的小张正通过镜片查看实时导航路线&#xff0c;眼前的虚拟箭头精准指引换乘方向&#xff1b;手术室里&#xff0c;主刀医生透过镜片看到患者血管的3D投影&#xff0c;如同获得透视眼般精准避开危险区域&#xff1b;装修现场&#xff0c;设…...

ubantu18.04(Hadoop3.1.3)Hive3.1.2安装指南

说明&#xff1a;本文图片较多&#xff0c;耐心等待加载。&#xff08;建议用电脑&#xff09; 注意所有打开的文件都要记得保存。本文的操作均在Master主机下进行 第一步&#xff1a;准备工作 本文是在之前Hadoop搭建完集群环境后继续进行的&#xff0c;因此需要读者完成我之…...

Hive 多表查询案例

文章目录 前提条件Hive 多表查询案例JOIN案例JOIN查询数据准备1. 内连接&#xff08;INNER JOIN&#xff09;2. 左外连接&#xff08;LEFT OUTER JOIN&#xff09;3. 右外连接&#xff08;RIGHT OUTER JOIN&#xff09;4. 全外连接&#xff08;FULL OUTER JOIN&#xff09;5. 多…...

4.23刷题记录(栈与队列专题)

第一部分&#xff1a;基础知识 栈先进后出&#xff0c;队列先进先出栈用stack实现&#xff0c;主要函数有pop&#xff0c;push&#xff0c;top队列由queue或者deque实现&#xff0c;主要函数有front&#xff0c;back&#xff0c;push&#xff0c;pop&#xff0c;emplace&#…...

Python常用的第三方模块之【jieba库】支持三种分词模式:精确模式、全模式和搜索引擎模式(提高召回率)

Jieba 是一个流行的中文分词Python库&#xff0c;它提供了三种分词模式&#xff1a;精确模式、全模式和搜索引擎模式。精确模式尝试将句子最精确地切分&#xff0c;适合文本分析&#xff1b;全模式则扫描文本中所有可能的词语&#xff0c;速度快但存在冗余&#xff1b;搜索引擎…...

Redisson实战:分布式系统中的五大典型应用场景

引言 在分布式系统架构中&#xff0c;数据一致性、高并发控制和资源协调是开发者面临的核心挑战。Redisson作为基于Redis的Java客户端&#xff0c;不仅提供了丰富的分布式对象和服务&#xff0c;还简化了分布式场景下的编程模型。本文将通过实际代码示例&#xff0c;解析Redis…...

webrtc建立连接的过程

WebRTC 连接全过程&#xff1a;从零到视频通话的每一步 WebRTC 是个神奇的技术&#xff0c;让浏览器直接进行点对点&#xff08;P2P&#xff09;音视频通话或数据传输&#xff0c;不用每次都靠服务器中转。想知道 Alice 和 Bob 是怎么通过 WebRTC 建立视频通话的吗&#xff1f…...

system verilog 语句 耗时规则

在 SystemVerilog 中&#xff0c;确实有一类语句是**不消耗仿真时间(zero simulation time)**的&#xff0c;我们一般叫它们&#xff1a; ✅ 零延迟语句&#xff08;Zero-Time Statements&#xff09; &#x1f539;1. 什么是“不费时间”的语句&#xff1f; 这些语句在仿真时…...