QT 项目 实现基于TCP的文件服务器/客户端,支持上传和下载

2023-05-16

Demo:下载地址: https://download.csdn.net/download/guorong520/12408371
没有csdn积分的小伙伴可以留言你的QQ邮箱,我会发送Demo,相互交流学习

一、程序运行图
客户端
在这里插入图片描述
服务端
在这里插入图片描述

二、功能描述
1.开启服务器,客户端进行连接。
2.客户端向服务器上传文件,也可以下载服务器文件到客户端本地。

三、源码如下
1.客户端
Client.cpp

#include "Client.h"
#include "ui_Client.h"

Client::Client(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Client)
{
    ui->setupUi(this);

    initClient();

    //1.上传
    connect(this, &Client::changeUpText, ui->labelUpTip, &QLabel::setText);
    connect(ui->btnConnect,&QPushButton::clicked,this,&Client::onConnect);
    connect(m_client,&QTcpSocket::connected,this,&Client::onAcceptState);
    connect(ui->btnUpload,SIGNAL(clicked(bool)),this,SLOT(onOpenFile()));
    connect(ui->btnSend,&QPushButton::clicked,this,&Client::onSendFile);
    //第一:此信号,不能写入局部函数中,其他函数可以执行此信号,但是参数仍保留上一次的值。
    //第二:触发此信号,不会立即执行槽函数,执行完这个局部函数,才会执行槽函数。
    //第三:信号槽不能重复定义
    connect(m_client, SIGNAL(bytesWritten(qint64)),this, SLOT(updateProgress(qint64)));

    //2.下载
    connect(this, &Client::changePuText, ui->labelPuTip, &QLabel::setText);
    connect(ui->btnRemote,&QPushButton::clicked,this,&Client::onResquestFileList);
    connect(ui->listWidget,&QListWidget::itemSelectionChanged,this,&Client::onGetDownFileName);
    connect(ui->btnDownload,&QPushButton::clicked,this,&Client::onDownRequest);
    connect(m_client, &QTcpSocket::readyRead, this, &Client::onReceiveProgress);

}

Client::~Client()
{
    delete ui;
}

void Client::initClient()
{
	setWindowTitle("文件客户端");
    ui->labelUpTip->setText(QString("请先连接:"));

	m_client = new QTcpSocket(this);
	m_totalBytes = 0;
	m_bytesWritten = 0;
	m_bytesTobeWrite = 0;
    m_cmd = 0;
    m_payloadSize = 64 * 1024;
    ui->progressBar->reset();
}

void Client::onConnect()
{
    if(ui->editHost->text().isEmpty() || ui->editPort->text().isEmpty())
    {
        QMessageBox::information(this,"提示"," 主机和端口不能为空");
        return;
    }
    emit changeUpText(QString("连接中"));
    m_client->connectToHost(ui->editHost->text(),ui->editPort->text().toInt());
    if(!m_client->waitForConnected(30000))
    {
        emit changeUpText(QString("连接失败!"));
    }
}

void Client::onAcceptState()
{
    emit changeUpText(QString("连接成功!"));
}

void Client::onOpenFile()
{
    emit changeUpText(QString("等待打开文件:"));
    m_fileName = QFileDialog::getOpenFileName(this);

    if(!m_fileName.isEmpty())
    {
        emit changeUpText(QString("文件 %1 打开成功!").arg(m_fileName));
    }
}

void Client::onSendFile()
{
    //不是消息,并且文件名为空
    if(m_cmd == 0 && m_fileName.isEmpty())
    {
        ui->labelUpTip->setText("请选择上传文件");
        return;
    }

    m_localFile = new QFile(m_fileName);
    if(!m_localFile->open(QFile::ReadOnly))
    {
        qDebug()<<"文件打开错误";
    }
    //计算文件大小
    m_totalBytes = m_localFile->size();

    //将发送缓冲区封装在QDataStream类型的变量中,方便传输数据
    QDataStream sendOut(&m_outBlock,QIODevice::WriteOnly);
    sendOut.setVersion(QDataStream::Qt_5_7);

    //构造临时文件头(总文件大小+文件名大小+消息类型+文件名)
    sendOut<<qint64(0)<<qint64(0)<<qint64(0)<<clearFilePath(m_fileName);;
    //计算文件总大小(总文件大小 = 文件大小 + 文件名 + sizeof(qint64)*3))
    m_totalBytes += m_outBlock.size();

    //将读写操作指向从头开始
    sendOut.device()->seek(0);
    //总大小和文件名大小和命令(必须为八个字节格式,里面存放值)
    sendOut<<m_totalBytes<<qint64((m_outBlock.size()-sizeof(qint64)*3))<<qint64(UPLOAD_FILE);
    m_cmd = UPLOAD_FILE;
    qDebug()<<"发送总大小"<<m_totalBytes<<"文件名大小"<<qint64((m_outBlock.size()-sizeof(qint64)*3))
           <<"文件名称"<<m_fileName<<"命令"<<m_cmd-3840;

    //修改待发送字节数
    m_bytesTobeWrite = m_totalBytes - m_client->write(m_outBlock); 
    m_outBlock.resize(0);
}

void Client::updateProgress(qint64 numBytes)
{
    //发送文件内容
    m_bytesWritten += numBytes;

    if(m_bytesTobeWrite > 0)
    {
        //100<200?100:200
        m_outBlock = m_localFile->read(qMin(m_bytesTobeWrite,m_payloadSize));
        m_bytesTobeWrite -= m_client->write((m_outBlock));
        m_outBlock.resize(0);
    }
    else
    {
        m_localFile->close();
    }

    ui->progressBar->setMinimum(0);
    ui->progressBar->setMaximum(100);
    ui->progressBar->setValue(m_bytesWritten*100/m_totalBytes);

    if(m_bytesWritten == m_totalBytes)
    {
        qDebug()<<"发送总大小:"<<m_totalBytes<<"已发送"<<m_bytesWritten<<"待发送"<<m_bytesTobeWrite;
        if(m_cmd == UPLOAD_FILE)
        {
            ui->labelUpTip->setText(QString("传送文件%1成功").arg(m_fileName));
        }
        if(m_cmd == SYN_FILE_LIST)
        {
            ui->labelPuTip->setText("请求同步列表已发送!");
        }
        if(m_cmd == DOWNLOAD_FILE)
        {
            ui->labelPuTip->setText("请求下载文件已发送!");
        }

        m_totalBytes = 0;
        m_bytesWritten = 0;
        m_bytesTobeWrite = 0;
        m_bytesReceived = 0;
        m_fileNameSize = 0;
        m_fileName = "";
        m_cmd = 0;
        m_outBlock.resize(0);
        m_localFile->close();
    }
}

void Client::onResquestFileList()
{
    m_localFile = new QFile("");
    if(!m_localFile->open(QFile::ReadOnly))
    {
        m_localFile->close();
    }
    QDataStream sendOut(&m_outBlock,QIODevice::WriteOnly);
    sendOut.setVersion(QDataStream::Qt_5_7);
    QString curFile = "";
    //构造临时文件头(总文件大小+文件名大小+消息类型+文件名)
    sendOut<<qint64(0)<<qint64(0)<<qint64(0)<<curFile;
    //计算文件总大小(总文件大小 = 文件大小 + 文件名 + sizeof(qint64)*3))
    m_totalBytes += m_outBlock.size();

    //将读写操作指向从头开始
    sendOut.device()->seek(0);
    //总大小和文件名大小和命令
    sendOut<<m_totalBytes<<qint64((m_outBlock.size()-sizeof(qint64)*3))<<qint64(SYN_FILE_LIST);
    m_cmd = SYN_FILE_LIST;
    qDebug()<<"发送总大小"<<m_totalBytes<<"文件名大小"<<qint64((m_outBlock.size()-sizeof(qint64)*3))
           <<"文件名称"<<m_fileName<<"命令"<<m_cmd-3840;

    //修改待发送字节数
    m_bytesTobeWrite = m_totalBytes - m_client->write(m_outBlock);
    displayFileList();
}

void Client::displayFileList()
{
    QString filePath = QApplication::applicationDirPath() + "/../../tcpClientFile/LocalFile";
    QDir dir(filePath);
    filePath = dir.absolutePath() + "/FILELIST.TXT";
    QFile fileList(filePath);
    if(!fileList.open(QFile::ReadOnly|QFile::Text))
    {
        qDebug()<<"Client::displayFileList :open filelist.txt error!"<<endl;
        return;
    }

    QTextStream input(&fileList);
    QString line;
    ui->listWidget->clear();
    while(input.readLineInto(&line))    //把所有文件名进行显示
    {
        //Qt中是编码格式是UTF-8-BOM
        ui->listWidget->addItem(line);
    }
}

QString Client::clearFilePath(QString filePath)
{
    QString fileName = filePath.right(filePath.size() - filePath.lastIndexOf('/')-1);
    return fileName;
}

void Client::onGetDownFileName()
{
    m_downFileName = ui->listWidget->currentItem()->text();

}

void Client::onDownRequest()
{
    if(m_downFileName.isEmpty())
    {
        ui->labelPuTip->setText("请先选择需要下载的文件");
        return;
    }
    m_localFile = new QFile("");
    if(!m_localFile->open(QFile::ReadOnly))
    {
        m_localFile->close();
    }
    QDataStream sendOut(&m_outBlock,QIODevice::WriteOnly);
    sendOut.setVersion(QDataStream::Qt_5_7);
    QString curFile = m_downFileName;
    //构造临时文件头(总文件大小+文件名大小+消息类型+文件名)
    sendOut<<qint64(0)<<qint64(0)<<qint64(0)<<curFile;
    //计算文件总大小(总文件大小 = 文件大小 + 文件名 + sizeof(qint64)*3))
    m_totalBytes += m_outBlock.size();

    //将读写操作指向从头开始
    sendOut.device()->seek(0);
    //总大小和文件名大小和命令
    sendOut<<m_totalBytes<<qint64((m_outBlock.size()-sizeof(qint64)*3))<<qint64(DOWNLOAD_FILE);
    m_cmd = DOWNLOAD_FILE;
    qDebug()<<"发送总大小"<<m_totalBytes<<"文件名大小"<<qint64((m_outBlock.size()-sizeof(qint64)*3))
           <<"文件名称"<<m_fileName<<"命令"<<m_cmd-3840;

    //修改待发送字节数
    m_bytesTobeWrite = m_totalBytes - m_client->write(m_outBlock);
}

void Client::onReceiveProgress()
{
    QDataStream in(m_client);

    in.setVersion(QDataStream::Qt_5_7);
    // 如果已接收到的数据小于等于24个字节,保存文件头结构

    if (m_bytesReceived<=sizeof(qint64)*3){
        //先取24个字节(bytesAvailable:套接字中的数据)
        if((m_client->bytesAvailable()>=sizeof(qint64)*3)&&(m_fileNameSize==0)){
            // 接收数据总大小信息和文件名大小信息
            in>>m_totalBytes>>m_fileNameSize>>m_cmd;
            m_bytesReceived +=sizeof(qint64)*3;
        }
        if((m_client->bytesAvailable()>=m_fileNameSize)&&(m_fileNameSize!=0)){
            // 接收文件名,并建立文件
            in>>m_fileName;
            m_bytesReceived+=m_fileNameSize;
            if(m_cmd == UPLOAD_FILE)
            {
                ui->labelPuTip->setText(tr("接收文件 %1 …").arg(m_fileName));
                //创建同名文件
                QString filePath = QApplication::applicationDirPath() + "/../../tcpClientFile/LocalFile";
                QDir dir(filePath);
                filePath = dir.absolutePath() + QString("/%1").arg(m_fileName);
                m_localFile = new QFile(filePath);

                if (!m_localFile->open(QFile::WriteOnly)){
                    qDebug() << "Server::onReceiveProgress: open file error!";
                    return;
                }
            }
        }
        else{
            return;
        }
        qDebug()<<"接收头部数据:"<<"总大小"<<m_totalBytes<<"头部大小"<<m_bytesReceived<<"命令"<<m_cmd-3840
               <<"文件名"<<m_fileName;
    }

    // 如果接收的数据小于总数据,那么写入文件
    if(m_bytesReceived<m_totalBytes) {
        m_bytesReceived+=m_client->bytesAvailable();
        m_inBlock = m_client->readAll();
        //
        m_localFile->write(m_inBlock);
        m_inBlock.resize(0);
    }

    ui->progressBar->setMinimum(0);
    ui->progressBar->setMaximum(100);
    ui->progressBar->setValue(m_bytesReceived*100/m_totalBytes);

    // 接收数据完成时,字段初始化,否则无法接收
    if (m_bytesReceived==m_totalBytes){
        qDebug()<<"接收文件内容:"<<"总大小"<<m_totalBytes<<"已接收"<<m_bytesReceived<<"文件名"<<m_fileName;
        if(m_cmd == UPLOAD_FILE)
        {
            ui->labelPuTip->setText(tr("接收文件 %1 成功!").arg(m_fileName));
            m_localFile->close();
            m_totalBytes = 0;
            m_bytesWritten = 0;
            m_bytesTobeWrite = 0;
            m_bytesReceived = 0;
            m_fileName = "";
            m_downFileName = "";
            m_cmd = 0;
            m_payloadSize = 64 * 1024;
            ui->progressBar->reset();
        }
        displayFileList();
    }
}

服务端
Server.cpp

#include "Server.h"
#include "ui_Server.h"
#include <QDir>

Server::Server(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Server)
{
    ui->setupUi(this);
    setWindowTitle("文件服务器");
    initServer();

    connect(ui->btnListen,&QPushButton::clicked,this,&Server::onStart);
    connect(ui->btnClose, &QPushButton::clicked, this , &Server::close);
    connect(&m_tcpServer,&QTcpServer::newConnection,this,&Server::onAcceptConnected);
    connect(&m_tcpServer,&QTcpServer::acceptError,this,&Server::displayError);
}

Server::~Server()
{
    delete ui;
}

void Server::initServer()
{
    m_fileNameSize = 0;
    m_totalBytes = 0;
    m_bytesReceived = 0;

    m_bytesWritten = 0;
    m_bytesTobeWrite = 0;

    //系统最大为64K,但可以自行修改系统设置
    m_payLoadSize = 64 * 1024;
    m_cmd = 0;
    m_tcpSocket = new QTcpSocket(this);
}

void Server::onStart()
{
    ui->labelTip->setText(QString("开始监听!"));
    if(!m_tcpServer.listen(QHostAddress::Any,PORT))
    {
        ui->labelTip->setText(QString("%1").arg(m_tcpServer.errorString()));
        m_tcpServer.close();
    }
}

void Server::onAcceptConnected()
{
    ui->labelTip->setText("连接成功!");
    m_tcpSocket = m_tcpServer.nextPendingConnection();
    //系统信号:readyRead/bytesWritten
    connect(m_tcpSocket, &QTcpSocket::readyRead, this, &Server::onReceiveProgress);
    connect(m_tcpSocket, SIGNAL(bytesWritten(qint64)),this, SLOT(onUpdateSendProgress(qint64)));
}

void Server::onReceiveProgress()
{
    //1.传输大文件时,界面不会卡住
    qApp->processEvents();
    QDataStream in(m_tcpSocket);
    in.setVersion(QDataStream::Qt_5_7);

    //2.如果已接收到的数据小于等于24个字节,保存文件头结构
    if (m_bytesReceived<=sizeof(qint64)*3)
    {
        if((m_tcpSocket->bytesAvailable()>=sizeof(qint64)*3)&&(m_fileNameSize==0))
        {
            //(1)接收数据总大小和文件名大小和命令
            in>>m_totalBytes>>m_fileNameSize>>m_cmd;
            m_bytesReceived +=sizeof(qint64)*3;
        }
        if((m_tcpSocket->bytesAvailable()>=m_fileNameSize)&&(m_fileNameSize!=0))
        {
            //(2)接收文件名
            in>>m_fileName;
            m_bytesReceived+=m_fileNameSize;

            //(3)解析命令:收到消息不处理,收到客户端上传命令建立文件
            if(m_cmd == UPLOAD_FILE)
            {
                ui->labelTip->setText(tr("接收文件 %1 …").arg(m_fileName));
                //创建同名文件
                QString filePath = QApplication::applicationDirPath() + "/../../tcpServerFile/RemoteFile";
                QDir dir(filePath);
                filePath = dir.absolutePath() + QString("/%1").arg(m_fileName);

                m_localFile = new QFile(filePath);
                if (!m_localFile->open(QFile::WriteOnly)){
                    qDebug() << "Server::onReceiveProgress: open file error!";
                    return;
                }
            }
        }
        else
        {
            return;
        }
        qDebug()<<"接收头部数据:"<<"总大小"<<m_totalBytes<<"头部大小"<<m_bytesReceived<<"命令"<<m_cmd-3840
               <<"文件名"<<m_fileName;
    }

    // 如果接收的数据小于总数据,那么写入文件
    if(m_bytesReceived<m_totalBytes) {
        m_bytesReceived+=m_tcpSocket->bytesAvailable();
        m_inBlock = m_tcpSocket->readAll();
        m_localFile->write(m_inBlock);
        m_inBlock.resize(0);
    }

    ui->progressBar->setMinimum(0);
    ui->progressBar->setMaximum(100);
    ui->progressBar->setValue(m_bytesReceived*100/m_totalBytes);

    // 接收数据完成时,字段初始化,防止数据污染
    if (m_bytesReceived == m_totalBytes)
    {
        qDebug()<<"接收文件内容:"<<"总大小"<<m_totalBytes<<"已接收"<<m_bytesReceived<<"文件名"<<m_fileName;
        if(m_cmd == UPLOAD_FILE)
        {
            ui->labelTip->setText(tr("接收文件 %1 成功!").arg(m_fileName));
            m_localFile->close();
            clearVar();
        }

        if(m_cmd == SYN_FILE_LIST)
        {
            ui->labelTip->setText("客户端请求文件同步列表");
            clearVar();
            getRemoteFileList();
            sendFile();
        }
        if(m_cmd == DOWNLOAD_FILE)
        {
            ui->labelTip->setText("客户端请求下载文件");
            clearVar();
            sendFile();
        }
    }
}

void Server::sendFile()
{
    if(m_cmd == SYN_FILE_LIST)
    {
        qDebug()<<"客户端请求远程文件列表";
        QString fileList = QApplication::applicationDirPath() + "/../../tcpServerFile";
        QDir dir(fileList);
        fileList = dir.absolutePath() + "/FILELIST.TXT";
        m_fileName = fileList;
    }

    if(m_cmd == DOWNLOAD_FILE)
    {
        qDebug()<<"客户端请求下载远程文件";
        QString fileList = QApplication::applicationDirPath() + "/../../tcpServerFile/RemoteFile";
        QDir dir(fileList);
        fileList = dir.absolutePath() + QString("/%1").arg(m_fileName);
        m_fileName = fileList;
    }

    qDebug()<<"发送文件名称:"<<m_fileName;
    m_localFile = new QFile(m_fileName);
    if(!m_localFile->open(QFile::ReadOnly))
    {
        qDebug()<<"文件打开错误";
    }
    m_totalBytes = m_localFile->size();

    QDataStream sendOut(&m_outBlock,QIODevice::WriteOnly);
    sendOut.setVersion(QDataStream::Qt_5_7);

    sendOut<<qint64(0)<<qint64(0)<<qint64(0)<<clearFilePath(m_fileName);
    //计算文件总大小(总文件大小 = 文件大小 + 文件名大小 + sizeof(qint64)*3))
    m_totalBytes += m_outBlock.size();
    qDebug()<<"发送总文件大小:"<<m_totalBytes;

    //将读写操作指向从头开始
    sendOut.device()->seek(0);
    //总长度和文件总长度和命令
    sendOut<<m_totalBytes<<qint64((m_outBlock.size()-sizeof(qint64)*3))<<qint64(UPLOAD_FILE);
    m_cmd = UPLOAD_FILE;

    //修改待发送字节数
    m_bytesTobeWrite = m_totalBytes - m_tcpSocket->write(m_outBlock);
    m_outBlock.resize(0);
}

void Server::onUpdateSendProgress(qint64 numBytes)
{
    //发送文件内容
    m_bytesWritten += numBytes;

    if(m_bytesTobeWrite > 0)
    {
        //100<200?100:200
        m_outBlock = m_localFile->read(qMin(m_bytesTobeWrite,m_payLoadSize));
        m_bytesTobeWrite -= m_tcpSocket->write((m_outBlock));
        m_outBlock.resize(0);
    }
    else
    {
        m_localFile->close();
    }
    //更新回传进度条
    ui->progressBar->setMinimum(0);
    ui->progressBar->setMaximum(100);
    ui->progressBar->setValue(m_bytesWritten*100/m_totalBytes);

    if(m_bytesWritten == m_totalBytes)
    {
        ui->labelTip->setText(QString("回传文件%1成功").arg(m_fileName));
        m_totalBytes = 0;
        m_bytesWritten = 0;
        m_bytesTobeWrite = 0;
        m_cmd = 0;
        m_outBlock.resize(0);
        m_localFile->close();
    }
}

void Server::getRemoteFileList()
{
    QString fileList = QApplication::applicationDirPath() + "/../../tcpServerFile/FILELIST.TXT";
    QDir dir(fileList);
    fileList = dir.absolutePath();
    QFile f(fileList);
    QTextStream out(&f);
    if(!f.open(QFile::WriteOnly|QFile::Text))
    {
        qDebug()<<"write FILELIST.TXT error!"<<endl;
        return;
    }

    QString remotePath = QApplication::applicationDirPath() + "/../../tcpServerFile/RemoteFile";
    QDir d(remotePath);
    remotePath = d.absolutePath();
    QDir r(remotePath);
    QStringList str;
    str << "*";
    QFileInfoList files = r.entryInfoList((QStringList)"*",
                                            QDir::Files|QDir::Dirs,QDir::DirsFirst);
    for(int i=0;i<files.count();i++)
    {
        QFileInfo tmpFileInfo = files.at(i);
        QString fileName = tmpFileInfo.fileName();
        //过滤"."和".."
        if(fileName=="."||fileName=="..")
            continue;
        if(tmpFileInfo.isFile())
            //写入TXT中
            out << fileName << endl;
        else
            continue;
     }
    f.close();
}

void Server::clearVar()
{
    m_fileNameSize = 0;
    m_totalBytes = 0;
    m_bytesReceived = 0;
    m_bytesWritten = 0;
    m_bytesTobeWrite = 0;
    m_inBlock.resize(0);
    m_outBlock.resize(0);
}

QString Server::clearFilePath(QString filePath)
{
    QString fileName = filePath.right(filePath.size() - filePath.lastIndexOf('/')-1);
    return fileName;
}

void Server::displayError(QAbstractSocket::SocketError socketError)
{
    qDebug() << "Server::displayError " << socketError;
    m_tcpServer.close();
    ui->progressBar->reset();
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

QT 项目 实现基于TCP的文件服务器/客户端,支持上传和下载 的相关文章

  • PVE安装win10并开启远程桌面

    接上一篇 一 win10安装镜像最新版下载 下载地址 xff1a https next itellyou cn 现在的win10最新版时22h2 文件名为zh cn windows 10 business editions version
  • Win10相机打开后显示灰色的原因(仅适用于联想笔记本)

    症状描述 xff1a 打开相机 xff0c 显示灰色 xff0c 中间有一个相机带斜杠的图标 我先说解决方法 xff0c 再吐槽 xff1a 如果网上的方法都不行 xff0c 就检查自己的笔记本是否安装了联想电脑管家 xff0c 如果有 x
  • Visual Studio 2015 tools for Unity 安装使用

    P1 xff1a 安装 微软好像把这个工具整合在Visual studio 2015一起了 xff0c 没找到单独的链接 CSDN链接 xff1a http download csdn net detail devilsomezeng 95
  • VMware部署Debian系统

    前面在手机和平板上安装了UserLAnd软件 xff0c 初步实现了随身携带Linux系统的小目标 但是前面也提到了目前存在一个小问题 xff0c 那就是没有办法远程登录 xff0c 简单调整了一下还没解决 xff0c 看来还是要简单学习一
  • Openstack关于Regions和Availability Zones

    声明 xff1a 本博客欢迎转发 xff0c 但请保留原作者信息 内容系本人学习 研究和总结 xff0c 如有雷同 xff0c 实属荣幸 xff01 原文地址 xff1a http blog csdn net gtt116 在AWS中有Re
  • Manjaro 安装搜狗输入法

    经历了长时间搜索和实践 xff0c 我终于安装好了搜狗输入法 xff0c 基本套路就还是按照大多数博客介绍的命令行装的 xff1a sudo pacman S fcitx im sudo pacman S fcitx configtool
  • layui:弹窗跨域问题 Uncaught DOMException: Blocked a frame with origin

    在日常开发中经常出现A系统调用B系统的相关功能 xff0c 在B系统中进行layer弹窗时 xff0c 提示错误信息 Uncaught DOMException xff0c 经过查询网上资料 xff0c 发现是跨域错误 仔细检查代码 xff
  • CentOS安装最新稳定版Jenkins

    文章目录 1 Java版本兼容列表2 JDK安装3 Jenkins安装3 1 定义Jenkins RPM仓库3 2 进行安装 4 Jenkins启动4 1 指定Java程序4 2 相关命令 5 FAQ5 1 目录介绍5 2 AWT is n
  • Codeforces Global Round 21参考代码

    Codeforces Global Round 21 A xff1a include lt iostream gt include lt algorithm gt include lt cstdio gt include lt cstrin
  • 有设计才艺的小伙伴千万不要错过GIMP

    GIMP是一个非常好的位图设计软件 xff01 支持LInux系统 xff0c Windows系统 xff0c Mac xff0c GIMP一直陪着我从Windows转到Linux xff0c 直到现在还在用 个人感觉比PhotoShop强
  • python下载

    python下载 1 打开python官网 网址 xff1a python org 1 1按照对应的操作系统选择 1 2下滑找到3 10 0 版本根据电脑配置选择64位或者32位 一般选择左列的稳定发行版 注意 xff0c 这里有embed
  • Android 捕获主线程异常崩溃

    一般情况下我们想要捕获全局异常会调用Thread setDefaultUncaughtExceptionHandler方法 xff1b 这个方法虽然能捕获所有线程的异常 xff0c 但如果是主线程发生未捕获异常 xff0c APP虽然不会崩
  • 使用cmake编译一段代码时出现VS2015 The C/CXX compiler identification is unknown

    打开CmakeError log 里面有如下错误 xff1a D Program Files Microsoft Visual Studio 14 0 VC bin x86 amd64 link exe ERRORREPORT QUEUE
  • Ubuntu安装VirtualBox6.1,报错依赖于libqt5opengl5...

    自己在安装Vbox6 1时遇到依赖问题 xff0c 多次尝试无法解决 xff0c 最后找到以下解决方法 由于网上看到的很多方法并不能解决问题 xff0c 这里将原文做转载 xff0c 希望能帮助到更多的人 1 方法一 xff1a 从Ubun
  • Debian 10(buster) 更换可用的国内软件源

    由于Debian 10 xff08 buster xff09 还比较新 xff0c 有很多源都使用不了 xff0c 有的还连接不上 xff0c 以下是亲自试过可以使用的源 xff0c 需要的小伙伴可以试试 163源 deb cdrom De
  • ubuntu 下搭建 Jenkins 并配置部署环境

    转载 xff1a https www cnblogs com shuoer p 9471839 html 前言 xff1a 因为要搭建Jenkins xff0c 试了很多办法都不行 xff0c 后来找到这篇博客装好了 xff0c 分享下 x
  • 批处理文件(.dat/.cmd)打开多个文件

    在window下 xff0c 有时候经常需要一次性打开多个文件 xff0c 如果都在一个目录下还好 xff0c 但是如果需要打开的文件分布在各个地方 xff0c 逐一打开还是挺麻烦的 通过批处理可以偷下懒 废话少说 xff0c 例文如下 x
  • STC 定时器/计数器2 操作详解 (基于STC89C52RC参考文档)

    一 认识STC定时器2 T2 STC 定时器2 xff08 即T2 xff09 是一个16位定时 计数器 通过设置特殊功能寄存器T2CON中的C T2位 xff0c 可将其作为定时器或计数器 xff08 特殊功能寄存器T2CON的描述如表1
  • 第五周作业 C题

    C题 平衡字符串 题目描述 xff1a 一个长度为 n 的字符串 s xff0c 其中仅包含 Q W E R 四种字符 如果四种字符在字符串中出现次数均为 n 4 xff0c 则其为一个平衡字符串 现可以将 s 中连续的一段子串替换成相同长
  • 第八周作业 B题

    B 猫猫向前冲 题目描述 xff1a 众所周知 xff0c TT 是一位重度爱猫人士 xff0c 他有一只神奇的魔法猫 有一天 xff0c TT 在 B 站上观看猫猫的比赛 一共有 N 只猫猫 xff0c 编号依次为1 xff0c 2 xf

随机推荐