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

[Qt]系统相关-文件操作-QFile、QFileInfo类以及相关操作函数

目录

一、Qt文件系统

1.Qt文件系统的介绍

2.Qt文件类

二、Qt文件的操作

1.文件的打开

2.文件的读写操作

3.关闭操作 

4.接口使用案例

5.获取文件的相关属性

三、文件的分类

1.文本文件

2.二进制文件

3.二者的区别


一、Qt文件系统

1.Qt文件系统的介绍

        文件操作是所有开发程序和开发语言必不可少的一个重要的部分,无论是C/C++、还是系统级别操作等提供了一套完整的文件操作接口,Qt作为了一个通用开发库,也必须提供了跨平台的文件操作能力。Qt中提供了很多文件的类,通过这些类能够对文件系统进行快速的操作了。

C语言标准库C++标准库Linux系统调用
打开文件fopen函数fstream类open函数
读取文件fread函数operator<<成员函数read函数
写入文件fwrite函数operator>>()成员函数write函数
关闭文件fclose函数close成员函数close函数

        而且Windows系统下,也会有Windows的一套系统调用接口去进行文件操作,那么不管是不同平台下,还是语言层面都有很多对文件的操作,为什么Qt还要自己去弄一套自己的文件操作呢?因为Qt的诞生节点有关,诞生的时候,C++还有没完整的标准化概念,所以Qt自己弄了一套方案。再编写Qt程序的时候,更推荐Qt自己提供的一套文件操作,因为QString等Qt自己的类和自己的文件操作配合会更方便一些。当然也可以使用上述的其他体系去实现文件操作。

2.Qt文件类

        在Qt中的文件操作中核心的无非也就是打开文件、读写文件和关闭文件的操作。Qt提供了一个QFile类,该类就可以实现上述的操作和对文件的管理。OFile类继承自OFileDevice类,该类中就提供了文件交互操作的底层功能。QFileDevice类的父亲是QIODevice,QIODevice的父亲就是所有类的祖先QObject类。

        QIODevice类是Qt中所有的输入输出设备的基础类,磁盘文件、网络通信的Socket套接字、串口、蓝牙等等都是属于输入输出型设备,所以都是继承于QIODevice类。

类名介绍
QFile用于文件操作和文件读写的类
QSaveFile用于安全保存文件的类,使用该类对象保存文件的时候,会先将数据写入一个临时文件,成功提交折后才会将数据写入最终的文件当中,如果保存过程中有错误的话,临死文件的内容不会写入最终文件,保证最终文件中不会出现数据残缺或丢失的问题,也就是说如果写入失败也会保留原有的数据。在保存比较大型的文件或者复杂格式的文件可以使用这个类。
QTemporaryFile用于创建临时文件的类,可以创建出一个唯一的临时文件,该QTemporaryFile对象销毁的时候,临时文件也就销毁了
QTcpSocket、QUdpSocket实现了TCP和UDP通信的类
QSerialPort实现了串口通信的类,通过该类可以实现计算机与串口设备的通信。串口是一个比较老的通信方式,一般是在嵌入式系统上用的较多。
QBluetoochSocket用于蓝牙通信的类
QPrecess用于启动外部程序的类,可以给程序传递参数内容。相当于fork、exec操作的封装。
QBuffer是以一个QByteArray对象作为缓冲区,对这个缓冲区进行I/O操作的类。相当于一个缓冲区类

二、Qt文件的操作

1.文件的打开

QFile::QFile(const QString &name);                                                  //创建QFile对象
virtual bool open(QIODevice::OpenMode mode) override;             //打开文件

        Qt中打开文件之前是需要创建一个QFile对象的并传递一个文件路径,之后配合着QFile类内部的open函数进行打开文件。open打开文件的函数传递的参数是文件的打开方式,也就是读方式、写方式、追加写等等方式,不用传递文件路径了,因为QFile对象内部已经记录了管理的文件所在的路径了。OpenMode是一个枚举类型,枚举出了一些打开文件的方式。

        QFile类中也提供了其他的open函数,但是没有上述的方便。需要传递C语言标准库中的文件对象FILE或者底层的文件描述符。

bool open(FILE *fh, QIODevice::OpenMode mode,
                                    QFileDevice::FileHandleFlags handleFlags = DontCloseHandle);

bool open(int fd, QIODevice::OpenMode mode,

                                    QFileDevice::FileHandleFlags handleFlags = DontCloseHandle);

2.文件的读写操作

读取操作函数

// 尽可能的读取文件内容

qint64 read(char* data, qint64 maxSize);

QByteArray read(qint64 maxSize);  

// 一次性将文件内容都读取出来

QByteArray readAll();

// 读取一行数据

qin64 readLine(char* data, qint64 maxSize);

QByteArray readLine(qint64 maxSize = 0);

        QByteArray返回值是一个字符数组,是Qt对于字符数组的封装,QString类中重载了operator =函数可以传递该QByteArray参数,所以很容易就可以转化为QString类型的字符串了。但是前提是打开的文件一个文本文件,如果是二进制文件的话,就会出现一些问题了。

写入操作函数

qint64 write(const char* data, qint64 maxSize);

qint64 write(const char* data);

qint64 write(const QByteArray& byteArray);

3.关闭操作 

virtual void close();

        一定要在操作文件之后关闭文件,从底层来说,系统的文件描述符表有上限,一直运行的程序如果不关闭的话,文件描述符越开越多,就会占满文件描述符表了,就会出问题。而且每一个文件描述符都会关联一个strutc file,系统也要将这些struct file结构体维护起来。还有就是如果不关闭的话,文件就会一直处于打开状态,在内存中,系统还要维护这些打开的文件。所以说文件操作完毕之后一定要关闭文件。

4.接口使用案例

案例:实现打开文件和保存文件的操作。

        该案例是模拟了一个记事本的操作,在菜单栏中提供了打开文件和保存文件的操作,打开文件关联的槽函数是,将指定路径文件的内容读取出来放入到多行输入文本框中,保存文件关联的槽函数是,将文本框中的内容写入到指定路径的文件当中。

        在保存文件的时候,需要QStrin的字符串文本类型重写转化为QByteArray类型,Qt中也提供了很多的转换函数。这里我们发现会有很多种转换的函数,而且需要我们自己手动转化,这是为什么呢?QByteArray存放的是我们打开的文件,存储的内容原始字节表示形式。而QString字符串是根据特定的编码格式将原始字节数据转化为了特定的文本格式了。       

        当QByteArray转化为QStirng的时候,默认是使用utf8编码方式进行转化。当然如果我们想要 转化为其他形式的话,也是需要使用Qt内置的一些接口进行转换的。当然前提是该文本类型不是二进制类型,否则二进制类型文件转化后会成一堆乱码。在打开文件的时候,一般都是打开的文本文件,所以默认使用的utf8的转换方式。而QString转化为QByteArray的时候,系统不知道我们想要保存的文件是什么类型,而且存放二进制文件和文本文件的几率基本上是一样的。所以说没有设置默认的存储类型,而是需要我们自己去设置。

QString转换QByteArray函数

const QString text = edit->toPlainText();
file.write(text.toUtf8());

 QByteArray转换QString函数

QByteArray latin1Array = "Hello, World";
QString str2 = QString::fromLatin1(latin1Array);QByteArray local8BitArray = "Hello, 世界";
QString str3 = QString::fromLocal8Bit(local8BitArray);

案例代码 

//edit是一个QTextEdit类型的成员函数,定义在mainwindow.h文件当中#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QFileDialog>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);//修改窗口标题this->setWindowTitle("记事本");//创建菜单栏QMenuBar* menubar = this->menuBar();this->setMenuBar(menubar);//添加菜单QMenu* menu = new QMenu("文件");menubar->addMenu(menu);//添加菜单项QAction* action1 = new QAction("打开文件");QAction* action2 = new QAction("保存文件");menu->addAction(action1);menu->addAction(action2);//创建一个输入框edit = new QTextEdit();//设置输入框的字体QFont font;font.setPixelSize(20);edit->setFont(font);//将窗口的中心部件设置为多行输入框this->setCentralWidget(edit);//将菜单项绑定槽函数connect(action1, &QAction::triggered, this, &MainWindow::openfile);connect(action2, &QAction::triggered, this, &MainWindow::savefile);
}MainWindow::~MainWindow()
{delete ui;
}//打开文件
void MainWindow::openfile()
{// 首先弹出一个选择文件的对话框QString path = QFileDialog::getOpenFileName(this);// 把选择的文件名显示到状态栏里面QStatusBar* statusbar = this->statusBar();statusbar->showMessage(path);//根据用户选择的路径,打开文件QFile file(path);bool ret = file.open(QIODevice::ReadOnly);if(ret == false){statusbar->showMessage(path + "打开失败");return;}//读取文件写入输入框QString text = file.readAll();//关闭文件file.close();//把读取的文件内容写入到输入框中。edit->setText(text);
}//保存文件
void MainWindow::savefile()
{//弹出一个保存文件对话框,选择保存的路径QString path = QFileDialog::getSaveFileName(this);//在状态栏中显示文件名QStatusBar* statusbar = this->statusBar();statusbar->showMessage(path);//根据选择的路径构造一个QFile对象,并打开文件QFile file(path);bool ret = file.open(QIODevice::WriteOnly);if(ret == false){statusbar->showMessage("保存失败");return;}//获取输入框的内容const QString text = edit->toPlainText();//写入到文件当中file.write(text.toUtf8());//关闭文件file.close();
}

 

5.获取文件的相关属性

        在Qt当中FileInfo类可以获取到Qt文件的相关属性。对于该操作在C/C++标准库中先前是没有相关此操作的,如果我们想要获得文件的属性就需要进系统调用进行获取,直到C++17才引入了相关的模块,提供了此功能。所以Qt就自己设计了一套获取文件相关属性的操作。

使用案例

void Widget::on_pushButton_clicked()
{//弹出对话框,选择文件并获取文件信息QString path = QFileDialog::getOpenFileName(this);//构造QFileInfo对象QFileInfo fileinfo(path);ui->textEdit->append("文件名: " + fileinfo.fileName());ui->textEdit->append("文件后缀: " + fileinfo.suffix());ui->textEdit->append("文件路径: " + fileinfo.path());ui->textEdit->append("文件大小: " + QString::number(fileinfo.size()));ui->textEdit->append("文件类型是否是普通文件: " + QString(fileinfo.isFile() == true ? "是" : "不是"));ui->textEdit->append("文件类似是否是一个目录: " + QString(fileinfo.isDir() == true ? "是" : "不是"));
}

        更多的QFileInfo内置的函数以及使用可以查看帮助文档。 

三、文件的分类

1.文本文件

        文本文件是由字符序列组成的文件内容,通常包含的是人类可以看懂的文本内容。这些字符按照一定的编码方式进行存储(UTF8、ASCII等),每个字符占用一个或者多个字节。其实这些字符底层也一定是一堆二进制数字,但是通过特定的编码,每个字符都会对应一个特定的二进制序列,会将这些二进制数据和我们能看懂的字符进行相互转化。

        文本文件常用于存储配置信息、源代码、日志文件、CSV 文件等。例如,配置文件.ini通常存储键值对,如key=value的形式;CSV 文件存储表格数据,以逗号分隔不同的字段。

2.二进制文件

        二进制文件存储的就是原始的二进制数据了,不是字符序列,大多数都是一些图像、视频和音频数据、数据库文件以及可执行文件等内容。这些数据不是并没有经过特定的编码格式排列,所以说并非是我们可以看懂的。通过一些特定的编码方式进行转化的话,转化后的也是一些乱码的字符数据。

3.二者的区别

  • 可读性:文本文件是给人类读的,所以可读性一定是很好的,而二进制文件的话,通常是给计算机看的,计算机会解析成一些图片、音频或者执行一些程序。
  • 存储效率:存储效率来说的话,文本文件的存储时,需要根据使用的编码方式进行特定格式的存储,而且一个文字可能会占用多个字节,例如UTF8中一个英文字符占用一个字节,而对于一些汉字来说要占用多个。而二进制文件的存储来说,不会进行字符编码,直接存储原始数据即可,存储效率比较高。对于一些需要存储大量数据的场景,如存储音频样本或图像像素,使用二进制文件可以更紧凑地存储数据,避免了字符编码的额外开销。但也并非绝对的,例如存储一个数字900,对于文本文件来说就是3个字符是3个字节,而对于二进制来说就是一个int类型的数字,需要4个字节了。
  • 跨平台性:文本文件在不同的操作系统下,换行符是不同的,在Windows上是\r\n,而linux下确实\n,所以可能会导致在跨平台处理文本文件的时候,需要进行换行字符的转化。而二进制文件来说虽然不受字符编码和换行符的影响,但是不同平台下可能对于数据的存储个数有不同的处理方式,例如大小端模式的区别。不同平台存储多字节数据的字节顺序可能不同,因此在跨平台使用二进制文件时,可能需要进行字节序的转换或其他数据格式的调整。

相关文章:

[Qt]系统相关-文件操作-QFile、QFileInfo类以及相关操作函数

目录 一、Qt文件系统 1.Qt文件系统的介绍 2.Qt文件类 二、Qt文件的操作 1.文件的打开 2.文件的读写操作 3.关闭操作 4.接口使用案例 5.获取文件的相关属性 三、文件的分类 1.文本文件 2.二进制文件 3.二者的区别 一、Qt文件系统 1.Qt文件系统的介绍 文件操作是所…...

C#高级:用Csharp操作鼠标和键盘

一、winform 1.实时获取鼠标位置 public Form1() {InitializeComponent();InitialTime(); }private void InitialTime() {// 初始化 Timer 控件var timer new System.Windows.Forms.Timer();timer.Interval 100; // 设置为 100 毫秒&#xff0c;即每 0.1 秒更新一次timer.…...

Mac 使用 GVM 管理多版本 Go 环境

使用 GVM 管理多版本 Go 环境 在本文中&#xff0c;我们将使用 gvm&#xff08;Go Version Manager&#xff09;工具管理本地多个 Go 语言版本。gvm 功能类似于 Python 的 Anaconda&#xff0c;可以方便地切换不同版本的 Go 环境&#xff0c;非常适合需要多版本开发与测试的场…...

25届合肥工业大学自动化考研复试攻略

本文内容&#xff0c;全部选自联盟自动化考研联盟企业店的&#xff1a;《合肥工业大学控制综合笔试篇》。后续会持续更新更多内容&#xff0c;记得关注哦~ 目录 Part1&#xff1a;复试指南具体内容 Part2&#xff1a;复试复习相关介绍 Part1&#xff1a;复试指南具体内容 1…...

【24】Word:小郑-准考证❗

目录 题目 准考证.docx 邮件合并-指定考生生成准考证 Word.docx 表格内容居中表格整体相较于页面居中 考试时一定要做一问保存一问❗ 题目 准考证.docx 插入→表格→将文本转换成表格→✔制表符→确定选中第一列→单击右键→在第一列的右侧插入列→布局→合并单元格&#…...

前瞻2024:前沿技术的全景洞察与深度剖析

在当今时代&#xff0c;前沿技术以前所未有的速度发展&#xff0c;深刻地改变着我们的生活、工作和社会的各个层面。从人工智能的迅猛发展到量子计算的逐步突破&#xff0c;从生物技术的不断创新到新能源技术的广泛应用&#xff0c;这些前沿技术正成为推动社会进步和经济发展的…...

告别手动编辑:如何用Python快速创建Ansible hosts文件?

在自动化运维领域&#xff0c;Ansible是一款非常强大的工具&#xff0c;它可以帮助我们管理和配置大量的服务器。为了让Ansible能够有效地管理这些服务器&#xff0c;我们需要一个hosts清单文件&#xff0c;该文件定义了Ansible要管理的目标主机。在实际应用中&#xff0c;我们…...

ESP32云开发二( http + led + lcd)

文章目录 前言先上效果图platformio.iniwokwi.tomldiagram.json源代码编译编译成功上传云端完结撒花⭐⭐⭐⭐⭐ 前言 阅读此篇前建议先看 此片熟悉下wokwi https://blog.csdn.net/qq_20330595/article/details/144289986 先上效果图 Column 1Column 2 platformio.ini wokwi…...

Java 基于微信小程序的原创音乐小程序设计与实现(附源码,部署,文档)

大家好&#xff0c;我是stormjun&#xff0c;今天为大家带来的是Java实战项目-基于微信小程序的原创音乐小程序设计与实现。该系统采用 Java 语言 开发&#xff0c;MySql 作为数据库&#xff0c;系统功能完善 &#xff0c;实用性强 &#xff0c;可供大学生实战项目参考使用。 博…...

JavaWeb开发(十五)实战-生鲜后台管理系统(二)注册、登录、记住密码

1. 生鲜后台管理系统-注册功能 1.1. 注册功能 &#xff08;1&#xff09;创建注册RegisterServlet&#xff0c;接收form表单中的参数。   &#xff08;2&#xff09;service创建一个userService处理业务逻辑。   &#xff08;3&#xff09;RegisterServlet将参数传递给ser…...

在stm32中C语言编写的程序中,一个整形数据是怎么存储的,高位在前还是低位在前

目录 举个例子 如何验证 小结 在 STM32&#xff08;基于 ARM Cortex-M 架构&#xff09;的系统中&#xff0c;默认是小端&#xff08;Little Endian&#xff09; 存储方式。也就是说&#xff0c;对于一个整型&#xff08;例如 32 位 int&#xff09;&#xff0c;它的最低有效…...

Redis系列之底层数据结构字典Dict

Redis系列之底层数据结构字典Dict Dict数据结构 Dict是Redis数据结构中使用最为频繁的复合型数据结构&#xff0c;本质上是一个哈希表 查看redis6.0版本的源码&#xff0c;链接&#xff1a;https://github.com/redis/redis/blob/6.0/src/dict.h 哈希表的结构定义&#xff1…...

CSS 溢出问题及解决方案:实用案例与技巧

在网页开发中&#xff0c;CSS 的布局和样式起着至关重要的作用&#xff0c;但经常会遇到一个棘手的问题——溢出问题。溢出是指元素内的内容超出了其设定的容器大小&#xff0c;这不仅会影响页面的美观&#xff0c;还可能干扰用户体验。本文将详细探讨 CSS 溢出问题的案例&…...

FastExcel 新一代的潮流 (EasyExcel)

目录 简介 FastExcel的特点 FastExcel使用方法详解 创建实体类和监听器 实现写入和读取功能 Excel转换为PDF 小结 FastExcel与EasyExcel的区别 结论 简介 FastExcel是由原EasyExcel作者在阿里巴巴宣布停止维护EasyExcel之后推出的升级版框架。它继承了EasyExcel的所有…...

使用ffmpeg提高mp4压缩比,减小文件体积【windows+ffmpeg+batch脚本】

文章目录 关于前情提要FFmpeg是什么使用脚本运行FFmpeg首先&#xff0c;下载ffmpeg.exe然后在视频相同位置写一个bat脚本运行压缩脚本 关于 个人博客&#xff0c;里面偶尔更新&#xff0c;最近比较忙。发一些总结的帖子和思考。 江湖有缘相见&#x1f91d;。如果读者想和我交…...

cuda从零开始手搓PB神经网络

cuda实现PB神经网络 基于上一篇的矩阵点乘&#xff0c;实现了矩阵的加减乘除、函数调用等。并且复用之前元编程里面写的梯度下降、Adam、NAdam优化方法。实现PB神经网络如下&#xff1a; #ifndef __BP_NETWORK_HPP__ #define __BP_NETWORK_HPP__ #include "matrix.hpp&quo…...

mac 安装mongodb

本文分享2种mac本地安装mongodb的方法&#xff0c;一种是通过homebrew安装&#xff0c;一种是通过tar包安装 homebrew安装 brew tap mongodb/brew brew upate brew install mongodb-community8.0tar包安装 安装mongodb 1.下载mongodb社区版的tar包 mongdb tar包下载地址 2…...

K8S-Pod资源清单的编写,资源的增删改查,镜像的下载策略

1. Pod资源清单的编写 1.1 Pod运行单个容器的资源清单 ##创建工作目录 mkdir -p /root/manifests/pods && cd /root/manifests/pods vim 01-nginx.yaml ##指定api版本 apiVersion: v1 ##指定资源类型 kind: Pod ##指定元数据 metadata:##指定名称name: myweb ##用户…...

【Maui】视图界面与数据模型绑定

文章目录 前言一、问题描述二、解决方案三、软件开发&#xff08;源码&#xff09;3.1 创建模型3.2 视图界面3.3 控制器逻辑层 四、项目展示 前言 .NET 多平台应用 UI (.NET MAUI) 是一个跨平台框架&#xff0c;用于使用 C# 和 XAML 创建本机移动和桌面应用。 使用 .NET MAUI&…...

JavaScript笔记基础篇02——运算符、语句、数组

黑马程序员视频地址&#xff1a;黑马程序员前端JavaScript入门到精通全套视频教程https://www.bilibili.com/video/BV1Y84y1L7Nn?vd_source0a2d366696f87e241adc64419bf12cab&spm_id_from333.788.videopod.episodes 目录 运算符 赋值运算符 ​编辑​编辑 一元运算符…...

visual studio 2022更改主题为深色

visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中&#xff0c;选择 环境 -> 常规 &#xff0c;将其中的颜色主题改成深色 点击确定&#xff0c;更改完成...

在四层代理中还原真实客户端ngx_stream_realip_module

一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡&#xff08;如 HAProxy、AWS NLB、阿里 SLB&#xff09;发起上游连接时&#xff0c;将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后&#xff0c;ngx_stream_realip_module 从中提取原始信息…...

NFT模式:数字资产确权与链游经济系统构建

NFT模式&#xff1a;数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新&#xff1a;构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议&#xff1a;基于LayerZero协议实现以太坊、Solana等公链资产互通&#xff0c;通过零知…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)

本期内容并不是很难&#xff0c;相信大家会学的很愉快&#xff0c;当然对于有后端基础的朋友来说&#xff0c;本期内容更加容易了解&#xff0c;当然没有基础的也别担心&#xff0c;本期内容会详细解释有关内容 本期用到的软件&#xff1a;yakit&#xff08;因为经过之前好多期…...

LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》

这段 Python 代码是一个完整的 知识库数据库操作模块&#xff0c;用于对本地知识库系统中的知识库进行增删改查&#xff08;CRUD&#xff09;操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 &#x1f4d8; 一、整体功能概述 该模块…...

搭建DNS域名解析服务器(正向解析资源文件)

正向解析资源文件 1&#xff09;准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2&#xff09;服务端安装软件&#xff1a;bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...

MySQL 8.0 事务全面讲解

以下是一个结合两次回答的 MySQL 8.0 事务全面讲解&#xff0c;涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容&#xff0c;并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念&#xff08;ACID&#xff09; 事务是…...

Web中间件--tomcat学习

Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机&#xff0c;它可以执行Java字节码。Java虚拟机是Java平台的一部分&#xff0c;Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...

PostgreSQL——环境搭建

一、Linux # 安装 PostgreSQL 15 仓库 sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-$(rpm -E %{rhel})-x86_64/pgdg-redhat-repo-latest.noarch.rpm# 安装之前先确认是否已经存在PostgreSQL rpm -qa | grep postgres# 如果存在&#xff0…...

Spring AI Chat Memory 实战指南:Local 与 JDBC 存储集成

一个面向 Java 开发者的 Sring-Ai 示例工程项目&#xff0c;该项目是一个 Spring AI 快速入门的样例工程项目&#xff0c;旨在通过一些小的案例展示 Spring AI 框架的核心功能和使用方法。 项目采用模块化设计&#xff0c;每个模块都专注于特定的功能领域&#xff0c;便于学习和…...