Qt 文件IO

news2024/11/29 1:22:05

目录

1. QFileDialog 文件选择对话框

示例代码

dialog.h

dialog.cpp

dialog.ui

运行效果:

2. QFileInfo 文件信息类

dialog.cpp

3. QFile 文件读写类

 UI与耗时操作

QThread 线程类

1 复现阻塞

dialog.h

dialog.cpp

 2.新建并启动子线程

mythread.h

mythread.cpp

 dialog.cpp

3.异步刷新

copythread.h

copythread.cpp

dialog.h

dialog.cpp

4.停止线程

 copythread.h

copythread.cpp

diaolog.h

dialog.cpp

运行效果:


1. QFileDialog 文件选择对话框

操作系统会提供一个统一样式的文件选择对话框,QFileDialog类可以直接调用系统自带的文件选择对话框。

QFileDialog继承自QDialog,这样的类直接使用静态成员函数调用。

// 参数1:父对象
// 参数2:标题栏
// 参数3:打开QFileDialog时所在的根目录,默认值为工作目录
// 参数4:文件格式过滤器
// 返回值:文件路径,选择失败返回空字符串
QString QFileDialog::getSaveFileName|getOpenFileName(
                             QWidget * parent = 0, 
                             const QString & caption = QString(),
                             const QString & dir = QString(),    
                             const QString & filter = QString()) [static]

示例代码

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include<QButtonGroup>
#include<QtWidgets>
namespace Ui {
class Dialog;
}

class Dialog : public QDialog
{
    Q_OBJECT

public:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    Ui::Dialog *ui;
    QButtonGroup *group;
    //获得读写路径
    void getReadPath();
    void getWritePath();
    QString readPath;//要读取的路径  成员变量
    QString writePath;//要另存储的路径
private slots:
    //按钮组点击的槽函数
    void btnsClickedSlot(int);
};

#endif // DIALOG_H

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    group=new QButtonGroup(this);
    group->addButton(ui->pushButtonOpen,1);
    group->addButton(ui->pushButtonSave,2);
    group->addButton(ui->pushButtonCopy,3);

    connect(group,SIGNAL(buttonClicked(int)),this,SLOT(btnsClickedSlot(int)));

}

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

void Dialog::getReadPath()
{
    //过滤器
    QString filter="所有格式(*.*);;C++(*.h *.cpp)";
    //父窗口 标题栏  打开QFileDialog时的文件根目录  文件过滤器
    QString path=QFileDialog::getOpenFileName(this,"打开","D:/",filter);
    if(path==""&&readPath=="")
    {
        //引导用户进行正确的处理
        QMessageBox::warning(this,"提示","请选择有效路径!");
        return;
    }
    readPath=path;
    //展示
    if(path!="")
         ui->textBrowserOpen->clear();
    ui->textBrowserOpen->append(readPath);
}

void Dialog::getWritePath()
{
    //过滤器
    QString filter="所有格式(*.*);;C++(*.h *.cpp)";
    //父窗口 标题栏  打开QFileDialog时的文件根目录  文件过滤器
    QString path=QFileDialog::getSaveFileName(this,"打开","D:/",filter);
    if(path==""&&writePath=="")
    {
        //引导用户进行正确的处理
        QMessageBox::warning(this,"提示","请选择有效路径!");
        return;
    }
    writePath=path;
    //展示
    if(path!="")
         ui->textBrowserSave->clear();
    ui->textBrowserSave->append(writePath);
}
void Dialog::btnsClickedSlot(int id)
{
    if(id == 1)
    {
       getReadPath();
    }else if(id == 2)
    {
       getWritePath();
    }else if(id == 3)
    {

    }
}

dialog.ui

运行效果:

2. QFileInfo 文件信息类

QFileInfo类用于获取文件信息。

相关函数如下:

// 构造函数
// 参数是文件路径,如果路径无效,对象仍然会创建成功
QFileInfo::QFileInfo(const QString & file)
// 判断对应路径下的文件是否存在
bool QFileInfo::exists() const
// 创建时间
QDateTime QFileInfo::created() const
// 上次修改时间
QDateTime QFileInfo::lastModified() const
// 上次读取时间
QDateTime QFileInfo::lastRead() const
// 是否可读
bool QFileInfo::isReadable() const
// 是否可写
bool QFileInfo::isWritable() const
// 获得文件大小,单位字节,如果文件不存在返回0
qint64 QFileInfo::size() const

dialog.cpp

void Dialog::showFileMessage()
{
    //创建文件信息类对象
    QFileInfo info(readPath);
    //获得创建时间
    QString time=info.created().toString("yyyy-MM-dd hh:mm:ss");
    ui->textBrowserOpen->append(time.prepend("创建时间"));
    //是否可读
    bool result=info.isReadable();
    if(result)
        ui->textBrowserOpen->append("可读");
    else
        ui->textBrowserOpen->append("不可读");
    //获取文件大小
    qint64 size=info.size();
    QString text;
    text.setNum(size).prepend("文件大小:").append("字节");
    ui->textBrowserOpen->append(text);

}
void Dialog::copy()
{
    //读写的对象
    QFile readFile(readPath);
    QFile writeFile(writePath);
    if(!readFile.exists())
    {
        QMessageBox::warning(this,"提示","请选择有效的读写路径!");
        return;
    }
    //屏蔽拷贝按钮
    ui->pushButtonCopy->setEnabled(false);
    ui->pushButtonCopy->setText("拷贝中");
    //使用只读模式打开数据流
    readFile.open(QIODevice::ReadOnly);
    writeFile.open(QIODevice::WriteOnly);

    qint64 totalSize=readFile.size();//文件总大小
    qint64 hasCopied=0;//已经读写的数据量

    //字节数组类
    QByteArray buffer;
    while(!readFile.atEnd())//循环读取 是否位于末端
    {
        buffer=readFile.read(1024);//一次读取1kb
        writeFile.write(buffer);
    }
    //收尾
    writeFile.flush();
    writeFile.close();
    readFile.close();
    //屏蔽拷贝按钮
    ui->pushButtonCopy->setEnabled(true);
    ui->pushButtonCopy->setText("开始拷贝");
    QMessageBox::information(this,"通知",writePath.prepend("文件拷贝完成,请查看"));
}

void Dialog::btnsClickedSlot(int id)
{
    if(id == 1)
    {
       getReadPath();
    }else if(id == 2)
    {
       getWritePath();
    }else if(id == 3)
    {
      copy();
    }
}

3. QFile 文件读写类

用于读写文件,需要注意的是QFile间接继承QIODevice类,QIODevice类是Qt所有IO类的基类,QIODevice类中规定了一些最基础的IO接口,本节讲解的这些接口,在后续其它IO类中也可以使用。

QFile的常用函数如下:

// 参数为文件路径
QFile::QFile(const QString & name)
// 判断对应路径下的文件是否存在
bool QFile::exists() const
// 打开数据流
// 参数为打开模式
// 返回值为打开的结果
bool QIODevice::open(OpenMode mode) [virtual]
// 读取的数据流是否位于末端
bool QIODevice::atEnd() const [virtual]
// 读取maxSize个字节到返回值的字节数组对象中
// 注意maxSize表示最大数量,不一定是实际数量
QByteArray QIODevice::read(qint64 maxSize)
// 输出到制定的位置
// 参数是输出的内容
// 返回值是实际的输出量
qint64 QIODevice::write(const QByteArray & byteArray)
// 清空输出流的缓存数据,返回值是结果
bool QFileDevice::flush()
// 关闭数据流
void QIODevice::close() [virtual]
// 获取剩余可读的数据量
qint64 QIODevice::size() const [virtual]

dialog.cpp

void Dialog::copy()
{
    //读写的对象
    QFile readFile(readPath);
    QFile writeFile(writePath);
    if(!readFile.exists())
    {
        QMessageBox::warning(this,"提示","请选择有效的读写路径!");
        return;
    }
    //屏蔽拷贝按钮
    ui->pushButtonCopy->setEnabled(false);
    ui->pushButtonCopy->setText("拷贝中");
    //使用只读模式打开数据流
    readFile.open(QIODevice::ReadOnly);
    writeFile.open(QIODevice::WriteOnly);

    qint64 totalSize=readFile.size();//文件总大小
    qint64 hasCopied=0;//已经读写的数据量

    //字节数组类
    QByteArray buffer;
    while(!readFile.atEnd())//循环读取 是否位于末端
    {
        buffer=readFile.read(1024);//一次读取1kb
        //输出
        hasCopied+=writeFile.write(buffer);
        //计算百分比
        int value=hasCopied*100/totalSize;
        //更新UI显示
        ui->progressBar->setValue(value);
    }
    //收尾
    writeFile.flush();
    writeFile.close();
    readFile.close();
    //屏蔽拷贝按钮
    ui->pushButtonCopy->setEnabled(true);
    ui->pushButtonCopy->setText("开始拷贝");
    QMessageBox::information(this,"通知",writePath.prepend("文件拷贝完成,请查看"));
}

 UI与耗时操作

Qt项目在默认的情况下只有一个线程,这个线程负责UI显示与用户的人机交互等程序运行所需的基础操作,因此这个线程也被称为主线程(UI线程)。

但是如果在主线程中执行一些耗时操作(例如IO、复杂算法等),会导致主线程原本的操作阻塞,无法及时响应,因此出现程序假死的现象。

此时强行关闭程序,由于耗时操作正在处理,导致关闭的命令也无法及时执行,操作系统检测到某个应用程序关闭无效,启动操作系统的保护机制,弹出对话框窗口引导用户是否强行关闭。

解决方法是新启动一个线程,让这个线程执行耗时操作,这样的线程被称为子线程。

QThread 线程类

1 复现阻塞

QThread类是Qt的线程类,其中使用睡眠函数可以非常方便的模仿耗时操作的效果。

// 使当前线程睡眠一段时间
// 参数为睡眠时间,单位毫秒
void QThread::msleep(unsigned long msecs) [static]
// 参数为睡眠时间,单位秒
void QThread::sleep(unsigned long secs) [static]

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QtWidgets>
//线程头文件
#include<QThread>

namespace Ui {
class Dialog;
}

class Dialog : public QDialog
{
    Q_OBJECT

public:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    Ui::Dialog *ui;
private slots:
    void btnSleepClickedSlot();
    void btnBoxClickedSlot();
};

#endif // DIALOG_H

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    connect(ui->pushButtonBox,SIGNAL(clicked()),
            this,SLOT(btnBoxClickedSlot()));
    connect(ui->pushButtonSleep,SIGNAL(clicked()),
            this,SLOT(btnSleepClickedSlot()));
}

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

void Dialog::btnSleepClickedSlot()
{
    //睡眠10S
    QThread::msleep(10000); //毫秒数
 // QThread::sleep(10);     //秒数
}

void Dialog::btnBoxClickedSlot()
{
    QMessageBox::information(this,"弹窗","出来了");
}

 

 2.新建并启动子线程

操作步骤如下所示:

1. 在Qt Creator中,选中项目名称,鼠标右键,点击“添加新文件”。

2. 在弹出的窗口中根据下图所示进行操作。

3. 在弹出的窗口中,依次输入类名(大驼峰)、基类名(QThread),选择类型信息(继承自QObject)后,点击“下一步”。

4. 在项目管理界面点击“完成”。可以在项目中看到已经创建的头文件和源文件。

5. 进入到自定义线程类的头文件,声明run函数。

// 子线程执行的起始点,在子线程对象调用start函数后,此函数自动被调用
// 此函数执行完成后,子线程也执行完成
void QThread::run() [virtual protected]

mythread.h

#ifndef MYTHREAD_H
#define MYTHREAD_H

#include <QThread>
#include <QDebug>
class MyThread : public QThread
{
    Q_OBJECT
public:
    explicit MyThread(QObject *parent = 0);
protected:
    //声明run函数
    void run();

signals:

public slots:

};

#endif // MYTHREAD_H

Fn+F1或双击F1选择QThread 查看其保护函数run()

 

6. 在自定义线程类的源文件中,定义run函数。

7. 在run函数中添加子线程要执行的耗时操作代码。

mythread.cpp

#include "mythread.h"

MyThread::MyThread(QObject *parent) :
    QThread(parent)
{

}
//定义run()函数
void MyThread::run()
{
    qDebug()<<"子线程开始";
    msleep(10000);//睡眠10s
    qDebug()<<"子线程结束";
}

8. 在主线程中创建子线程对象,调用start函数后开始子线程开始执行。

 dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    connect(ui->pushButtonBox,SIGNAL(clicked()),
            this,SLOT(btnBoxClickedSlot()));
    connect(ui->pushButtonSleep,SIGNAL(clicked()),
            this,SLOT(btnSleepClickedSlot()));
}

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

void Dialog::btnSleepClickedSlot()
{
    //创建子进程对象
    MyThread *mt=new MyThread(this);
    mt->start();
}

void Dialog::btnBoxClickedSlot()
{
    QMessageBox::information(this,"弹窗","出来了");
}

子线程控制睡眠耗时操作,同时可以点击弹窗ui操作。

 

3.异步刷新

在开发的过程中,经常遇到下面的场景:

子线程执行耗时操作,主线程显示耗时操作的信息。

此时需要子线程通过信号槽传参发送数据给主线程。需要注意的是,子线程只能执行耗时操作,主线程只能执行非耗时操作。

copythread.h

#ifndef COPYTHREAD_H
#define COPYTHREAD_H

#include <QThread>

class CopyThread : public QThread
{
    Q_OBJECT
public:
    explicit CopyThread(QObject *parent = 0);
protected:
    void run();//声明run函数

signals:
    //自定义信号
    void valueSignal(int);
public slots:

};

#endif // COPYTHREAD_H

copythread.cpp

#include "copythread.h"

CopyThread::CopyThread(QObject *parent) :
    QThread(parent)
{

}
//定义run函数
void CopyThread::run()
{
    //模拟文件拷贝的耗时操作
    for(int i=0;i<=100;i++)
    {
        msleep(50);//模拟拷贝消耗时间
        emit valueSignal(i);//发射进度值
    }
}

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include<QMessageBox>
//自定义线程类
#include"copythread.h"

namespace Ui {
class Dialog;
}

class Dialog : public QDialog
{
    Q_OBJECT

public:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    Ui::Dialog *ui;
private slots:
    void btnClickedSlot();//按钮点击的槽函数
    void valueSlot(int);//接收子进程信号参数的槽函数
};

#endif // DIALOG_H

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    //连接按钮点击的信号槽
    connect(ui->pushButton,SIGNAL(clicked()),
            this,SLOT(btnClickedSlot()));
}

void Dialog::btnClickedSlot()
{
    //创建并启动子线程
    CopyThread *ct=new CopyThread(this);
    //连接两个线程之间的信号槽
    connect(ct,SIGNAL(valueSignal(int)),this,SLOT(valueSlot(int)));
    ct->start();
}

void Dialog::valueSlot(int value)
{
    //更新进度条
    ui->progressBar->setValue(value);
    if(value==100)
        QMessageBox::information(this,"提示","拷贝完成");
}
Dialog::~Dialog()
{
    delete ui;
}

4.停止线程

介绍两种停止线程运行的方式:

  • 调用terminate函数,不推荐使用,因为这种方式是强制停止线程运行,可能导致占用的资源无法释放。
void QThread::terminate() [slot]
  • 使用标志位,耗时操作往往伴随着循环,可以给循环体增加一个标志位,通过控制这个标志位的值使循环正常跳出,从而使run函数正常结束。

 copythread.h

#ifndef COPYTHREAD_H
#define COPYTHREAD_H

#include <QThread>

class CopyThread : public QThread
{
    Q_OBJECT
public:
    explicit CopyThread(QObject *parent = 0);
    bool isRunning=true;//是否运行的标志位
protected:
    void run();

signals:
    //自定义信号
    void valueSignal(int);
public slots:

};

#endif // COPYTHREAD_H

copythread.cpp

#include "copythread.h"

CopyThread::CopyThread(QObject *parent) :
    QThread(parent)
{

}
void CopyThread::run()
{
    //模拟文件拷贝的耗时操作
    for(int i=0;i<=100&&isRunning;i++)
    {
        msleep(50);//模拟拷贝消耗时间
        emit valueSignal(i);//发射进度值给主线程
    }
}

diaolog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include<QMessageBox>
//自定义线程类
#include"copythread.h"

namespace Ui {
class Dialog;
}

class Dialog : public QDialog
{
    Q_OBJECT

public:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    Ui::Dialog *ui;
    CopyThread *ct=NULL;//成员变量
private slots:
    void btnClickedSlot();//按钮点击的槽函数
    void valueSlot(int);//接收子进程信号参数的槽函数
    void btnBClickedSlot();//标志位停止的槽函数
};

#endif // DIALOG_H

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    //连接按钮点击的信号槽
    connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(btnClickedSlot()));
}
Dialog::~Dialog()
{
    delete ui;
}

void Dialog::btnClickedSlot()
{
    //创建并启动子线程
    ct=new CopyThread(this);
    //连接两个线程之间的信号槽
    connect(ct,SIGNAL(valueSignal(int)),this,SLOT(valueSlot(int)));
    //连接系统自带的强制停止的槽函数
    connect(ui->pushButtonT,SIGNAL(clicked()), ct,SLOT(terminate()));
    //连接标志位停止的槽函数
    connect(ui->pushButtonB,SIGNAL(clicked()),this,SLOT(btnBClickedSlot()));
    ct->start();
}

void Dialog::valueSlot(int value)
{
    //接收进度值并更新进度条
    ui->progressBar->setValue(value);
    if(value==100)
        QMessageBox::information(this,"提示","拷贝完成");
}

void Dialog::btnBClickedSlot()
{
    if(ct!=NULL)
    //标志位停止
        ct->isRunning=false;
}

运行效果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/519795.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Py之tf2onnx:tf2onnx库的简介、安装、使用方法之详细攻略

Py之tf2onnx&#xff1a;tf2onnx库的简介、安装、使用方法之详细攻略 目录 tf2onnx库的简介 tf2onnx库的安装 tf2onnx库的使用方法 1、基础用法 tf2onnx库的简介 tf2onnx是一个将TensorFlow&#xff08;tf-1.x或tf-2.x&#xff09;、keras、tensorflow.js和tflite模型转换…

【python安装】linux环境安装python

linux环境安装python 小白都能看懂的python安装前置步骤下载python安装python 小白都能看懂的python安装 前置步骤 使用 python -V 或者 python -version 查看是否安装python如果Linux有python3需要更新指定版本的话&#xff0c;先把自带的删除&#xff0c;输入 rpm -qa|grep…

JavaScript通过js的方式来计算平行四边形的面积的代码

以下为通过js的方式来计算平行四边形的程序代码和运行截图 目录 前言 一、通过js的方式来计算平行四边形&#xff08;html部分&#xff09; 1.1 运行流程及思想 1.2 代码段 二、通过js的方式来计算平行四边形&#xff08;js部分&#xff09; 2.1 运行流程及思想 2.2 代码…

算法修炼之练气篇——练气六层

博主&#xff1a;命运之光 专栏&#xff1a;算法修炼之练气篇 前言&#xff1a;每天练习五道题&#xff0c;炼气篇大概会练习200道题左右&#xff0c;题目有C语言网上的题&#xff0c;也有洛谷上面的题&#xff0c;题目简单适合新手入门。&#xff08;代码都是命运之光自己写的…

算法修炼之练气篇——练气十七层

博主&#xff1a;命运之光 专栏&#xff1a;算法修炼之练气篇 前言&#xff1a;每天练习五道题&#xff0c;炼气篇大概会练习200道题左右&#xff0c;题目有C语言网上的题&#xff0c;也有洛谷上面的题&#xff0c;题目简单适合新手入门。&#xff08;代码都是命运之光自己写的…

SpringBoot+Token+Redis+Lua+自动续签极简分布式锁Token登录方案

前言 用SpringBoot做一个项目&#xff0c;都要写登录注册之类的方案 使用Cookie或Session的话&#xff0c;它是有状态的&#xff0c;不符合现代的技术 使用Security或者Shiro框架实现起来比较复杂&#xff0c;一般项目无需用那么复杂 使用JWT它虽然是无状态的&#xff0c;也可…

微信开发者之AppID和AppSecret举例子

-- 请不要为爱你的人流泪&#xff0c;因为爱你的人不会让你流泪&#xff01; 序 今天对这2东西做个相对全面的介绍&#xff0c;不一定深入&#xff0c;但是对实际开发还是很有必要的 我们在微信开发中总是会绕不开2个单词&#xff1a; AppID&#xff1a;开发者ID,有些叫AppK…

蓝桥杯题单day2【题目】

动态规划 调手表https://www.lanqiao.cn/problems/230/learning/?page1&first_category_id1&sortstudents_count&second_category_id3&tags%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92,%E5%9B%BD%E8%B5%9B 最优包含https://www.lanqiao.cn/problems/239/learning…

114.【Vue-细刷-05】

Vue-04 (二十八)、Vuex1.Vuex的简介(1).vuex是什么(2).什么时候使用Vuex(3).Vuex工作原理图 2.求和案列_纯Vue版本3.求和案列_Vuex(1).初始化状态(2).操作状态 4.求和案列_Vuex的getters(1).Vuex的getters类似于 Vue的computed 5.求和案列_Vuex中的mapSteat和mapGetters(1).靠自…

PY32F072 系列单片机,LQFP64, LQFP48, QFN32, LQFP32多种封装

PY32F072 系列微控制器采用高性能的 32 位 ARM Cortex-M0内核&#xff0c;宽电压工作范围的 MCU。嵌入高达 128Kbytes flash 和 16Kbytes SRAM 存储器&#xff0c;最高工作频率 72MHz。包含多种不同封装类型多款产品&#xff0c;LQFP64, LQFP48, QFN32, LQFP32。 PY32F072芯片…

C# 实现 Websocket通讯聊天 (管用、超好使,点个赞)

1、背景 WebSocket出现之前&#xff0c;Web端为了实现即时通讯&#xff0c;所用的技术都是Ajax轮询(polling)。轮询是在特定的的时间间隔&#xff08;如每1秒&#xff09;&#xff0c;由浏览器对服务器发出HTTP request&#xff0c;然后由服务器返回最新的数据给客服端的浏览器…

基于RV1126平台分类模型全流程部署(附工程)

基于RV1126平台分类模型全流程部署 环境安装模型训练ONNX模型转换RKNN模型转换可执行文件上板推理 环境安装 首先要在虚拟机上安装瑞芯微Rv1126的SDK&#xff0c;重要的是要具有rknn_toolchain 一般在以下路径&#xff1a; sdk/external/rknn-toolkit 按照doc里面的步骤安装即…

多模态:MiniGPT-4

多模态&#xff1a;MiniGPT-4 IntroductionMethodlimitation参考 Introduction GPT-4具有很好的多模态能力&#xff0c;但是不开源。大模型最近发展的也十分迅速&#xff0c;大模型的涌现能力可以很好的迁移到各类任务&#xff0c;于是作者猜想这种能力可不可以应用到多模态模…

物联网常见协议之 Amqp 协议及使用场景解析

引言 本文围绕 AMQP 协议&#xff0c;为大家详细解析 AMQP 协议、核心技术亮点、多协议之间的对比以及使用实践&#xff0c;并介绍华为云 IoT 通过 Amqp 协议如何为开发者和企业提供了更加灵活和高效的通信方式&#xff0c;使得物联网应用得以在各个领域得到更广泛的推广和应用…

项目文档(request页面代码逻辑)

项目文档 1. 封装请求基地址 2. 添加请求拦截器并设置请求头 作用 在向服务器发送请求时,很多请求都需要在请求头中携带token&#xff0c;每一次去请求都写请求头很麻烦&#xff0c;所以我们写一个请求拦截器&#xff0c;统一拦截并添加一个请求头 代码部分 // 请求拦截器 req…

[架构之路-194]-《软考-系统分析师》- 软件复用技术之软件产品线

目录 1. 思想来源&#xff1a;产品线 1.1 硬件产品线 1.2. 产品组合 2. 软件产品线 2.1 思想来源&#xff1a; 2.2 为什么使用软件产品线&#xff1f; 2.3 软件产品线是一种软件架构 2.4 软件产品线详解 2.5 软件产品线的双生命周期的模型 2.6 软件产品线建立方式 …

Kali E:Unable to locate package错误解决

默认的新装的kali 可能都会遇到这个安装报错E: Unable to locate package httrack问题&#xff0c;今天我记录下彻底解决过程和效果。 Command httrack not found, but can be installed with: apt install httrack Do you want to install it? (N/y)y apt install httrack Re…

介绍动作识别数据集:“NTU RGB+D”数据集和“NTU RGB+D 120”数据集

动作识别数据集&#xff1a;“NTU RGBD”数据集和“NTU RGBD 120”数据集 &#xff08;还包括AUTH UAV手势数据集&#xff1a;NTU 4级&#xff09; 本页介绍两个数据集&#xff1a;“NTU RGBD”和“NTU RGBD 120”。 “NTU RGBD”包含60个动作类和56&#xff0c;880个视频样本…

傅里叶分析的历史背景

目录 1. Fourier级数(三角级数)的历史背景 2. 圆和复平面 3. Fourier的大胆猜想 1. Fourier级数(三角级数)的历史背景 自古以来&#xff0c;圆形一直是(现在仍然是&#xff09;最简单的抽象理解形状。您只需要一个中心点和一个半径就可以了。圆上的所有点与圆心的距离都是固定…

无监督域适应 (UDA)(1)

一、定义 1、无监督域自适应 Unsupervised domain adaptation 经典机器学习假设训练集和测试集来自相同的分布。 然而&#xff0c;这个假设在现实世界的应用程序中可能并不总是成立&#xff0c;例如&#xff0c;数据来源不同。 这种情况下&#xff0c;域分布之间会存在差异…