Qt文件系统-二进制文件读写

实例功能概述

除了文本文件之外,其他需要按照一定的格式定义读写的文件都称为二进制文件。每种格式的二进制文件都有自己的格式定义,写入数据时按照一定的顺写入,读出时也按照相应的顺读出。例如地球物理中常用的SEG-Y格式文件,必须按照其标准格式要求写入数据才符合这种文件的格式规范,读取数据时也需要按照格式定义来读出。

Qt 使用 QFile 和 QDataStream 进行二进制数据文件的读取。QFile 负责文件的 IO 设备接口,即与文件的物理交互,QDataStream 以数据流的方式读取文件内容或写入文件内容。

我们依然是用一个例子来演示二进制文件读写,界面如下:

实例中以表格编辑一个数据表,采用 Model/View结构,编辑后的数据保存为二进制文件。

根据 QDataStream 保存文件时使用的数据编码的方式不同,可以保存为两种文件。

  1. 用 Qt 预定义的编码保存各种类型的数据文件,定义文件后缀为“.stm”。Qt 预定义编码是指在写入某个类型数据,如整形数、字符串等到文件流时,使用 Qt 预定义的编码。可以将这种 Qt 预定义数据格式编码类比 HTML 的标记符,Qt 写入某种类型的数据时用了 Qt 预定义的标记符,独处数据时,根据标记符读出数据。使用 Qt 预定义编码保存流文件,某些字节是 QDataStream 自己写入的,我们并不完全知道文件内每个字节的意义,但使用 QDataStream 可以读出相应的数据。
  2. 标准编码数据文件,定义文件后缀为“.dat”。在将数据写到文件时,完全使用数据的二进制原始内容,每个字节都有具体定义,在读出数据时,只需根据每个字节的定义读出数据即可。

编写的例子具有以下功能:

  • 可以在表格内编辑数据,同样的表格数据内容可以保存为两种格式的文件,Qt 预定义编码文件(stm 文件)和标准编码文件(dat 文件);
  • 界面上的表格数据可以修改,可以添加行,插入列,删除行;
  • 可以读取 stm 文件或 dat 文件,虽然文件格式不一样,但对相同的界面数据表存储的文件的实质内容是由于的。

实例的主窗口使用了 Model/View结构、标准项数据模型(QStandardItemModel)和选择模型(QItemSelectionModel),界面上使用了 QTableView 组件,还有代理组件。这些设计 Model/View

的设计,以后得文章会讲。

为了便于理解后面的程序,这里给出 MainWindow 类中自定义的一些变量和函数,具体如下:

class MainWindow : public QMainWindow
{Q_OBJECT
private://用于状态栏的信息显示QLabel  *LabCellPos;    //当前单元格行列号QLabel  *LabCellText;   //当前单元格内容QWIntSpinDelegate    intSpinDelegate; //整型数QWFloatSpinDelegate  floatSpinDelegate; //浮点数QWComboBoxDelegate   comboBoxDelegate; //列表选择QStandardItemModel  *theModel;//数据模型QItemSelectionModel *theSelection;//Item选择模型void    resetTable(int aRowCount);  //表格复位,设定行数bool    saveDataAsStream(QString& aFileName);//将数据保存为数据流文件bool    openDataAsStream(QString& aFileName);//读取数据流文件bool    saveBinaryFile(QString& aFileName);//保存为二进制文件bool    openBinaryFile(QString& aFileName);//打开二进制文件
};

Qt 预定义编码文件的读写

保存为 stm 文件

首先看文件保存功能,因为从文件保存功能的代码可以看出文件内数据的存储顺序。在 UI 界面上点击“保存 stm”文件。可以使用 Qt 预定义编码方式保存文件。此按钮响应代码如下:

void MainWindow::on_actSave_triggered()
{ //以Qt预定义编码保存数据文件QString curPath=QDir::currentPath();QString aFileName=QFileDialog::getSaveFileName(this,tr("选择保存文件"),curPath,"Qt预定义编码数据文件(*.stm)");if (aFileName.isEmpty())return; //if  (saveDataAsStream(aFileName)) //保存为流数据文件QMessageBox::information(this,"提示消息","文件已经成功保存!");
}
bool MainWindow::saveDataAsStream(QString &aFileName)
{//将模型数据保存为Qt预定义编码的数据文件QFile aFile(aFileName);  //以文件方式读出if (!(aFile.open(QIODevice::WriteOnly | QIODevice::Truncate)))return false;QDataStream aStream(&aFile);aStream.setVersion(QDataStream::Qt_5_9); //设置版本号,写入和读取的版本号要兼容qint16  rowCount=theModel->rowCount(); //数据模型行数qint16  colCount=theModel->columnCount(); //数据模型列数aStream<<rowCount; //写入文件流,行数aStream<<colCount;//写入文件流,列数//获取表头文字for (int i=0;i<theModel->columnCount();i++){QString str=theModel->horizontalHeaderItem(i)->text();//获取表头文字aStream<<str; //字符串写入文件流,Qt预定义编码方式}//获取数据区的数据for (int i=0;i<theModel->rowCount();i++){QStandardItem* aItem=theModel->item(i,0); //测深qint16 ceShen=aItem->data(Qt::DisplayRole).toInt();aStream<<ceShen;// 写入文件流,qint16aItem=theModel->item(i,1); //垂深qreal chuiShen=aItem->data(Qt::DisplayRole).toFloat();aStream<<chuiShen;//写入文件流, qrealaItem=theModel->item(i,2); //方位qreal fangWei=aItem->data(Qt::DisplayRole).toFloat();aStream<<fangWei;//写入文件流, qrealaItem=theModel->item(i,3); //位移qreal weiYi=aItem->data(Qt::DisplayRole).toFloat();aStream<<weiYi;//写入文件流, qrealaItem=theModel->item(i,4); //固井质量QString zhiLiang=aItem->data(Qt::DisplayRole).toString();aStream<<zhiLiang;// 写入文件流,字符串aItem=theModel->item(i,5); //测井bool quYang=(aItem->checkState()==Qt::Checked);aStream<<quYang;// 写入文件流,bool型}aFile.close();return true;
}

自定义函数 saveDataAsStream()将表格的数据模型 thisModel 的数据保存为一个 stm 文件。代码首先是创建 QFile 对象 aFile 打开文件,然后创建 QDataStream 对象 aStream 与 QFile 对象关联。

在开始写数据流前,为 QDataStream 对象 aStream 设置版本号,即调用 setVersion()函数,并传递一个 QDataStream::Version 枚举类型的值。

aStream.setVersion(QDataStream::Qt_5_9);

注意:以 Qt 的预定义类型编码保存的文件需要指定流版本号,因为每个版本的 Qt 对数据类型的编码可能有差别,需要保证写文件和读文件的流版本兼容。

接下来就是按照需要保存数据的顺序写入文件流。例如在文件开始,先写入行数和列数两个 qint16 的整数。因为行数和列数关系到后面的数据时如何组织的,英雌在读取文件数据时,首先读取这两个整数,然后根据数据存储方式的约定,就知道后续数据该如何读取了。向文件写入数据时,直接用流的输入操作,如:

aStream<<rowCount; //写入文件流,行数
aStream<<colCount; //写入文件流,列数

在读取各列的表头字符串之后,将其写入数据流。然后逐行扫描表格的数据模型,将每一行的列数据写入数据流。数据流写入数据时都使用运算符“<<”,不论写的是 qint16、qreal,还是其他字符串。除了可以写入基本数据类型以外,QDataStream 流操作还可以写入很多其他类型的数据,如 QBrush、QColor、QImage、QIcon 等,这些称为可序列化的数据类型。

QDataStream 以流操作写入这些数据时,我们并不知道文件里每个字节是如何存储的,但是知道数据写入顺序,以及每次写入数据的类型。在文件数据读出时,只需按照顺序和类型对应读出即可。

读取 stm 文件

按钮“打开 stm 文件”的响应代码及相关函数代码,选择需要打开的 stm 文件后,主要是调用自定义函数 openDataAsStream()将其打开。

bool MainWindow::openDataAsStream(QString &aFileName)
{ //从Qt预定义流文件读入数据QFile aFile(aFileName);  //以文件方式读出if (!(aFile.open(QIODevice::ReadOnly)))return false;QDataStream aStream(&aFile); //用文本流读取文件aStream.setVersion(QDataStream::Qt_5_9); //设置流文件版本号qint16  rowCount,colCount;aStream>>rowCount; //读取行数aStream>>colCount; //列数this->resetTable(rowCount); //表格复位//获取表头文字QString str;for (int i=0;i<colCount;i++)aStream>>str;  //读取表头字符串//获取数据区文字,qint16  ceShen;qreal  chuiShen;qreal  fangWei;qreal  weiYi;QString  zhiLiang;bool    quYang;QStandardItem   *aItem;QModelIndex index;for (int i=0;i<rowCount;i++){aStream>>ceShen;//读取测深, qint16index=theModel->index(i,0);aItem=theModel->itemFromIndex(index);aItem->setData(ceShen,Qt::DisplayRole);aStream>>chuiShen;//垂深,qrealindex=theModel->index(i,1);aItem=theModel->itemFromIndex(index);aItem->setData(chuiShen,Qt::DisplayRole);aStream>>fangWei;//方位,qrealindex=theModel->index(i,2);aItem=theModel->itemFromIndex(index);aItem->setData(fangWei,Qt::DisplayRole);aStream>>weiYi;//位移,qrealindex=theModel->index(i,3);aItem=theModel->itemFromIndex(index);aItem->setData(weiYi,Qt::DisplayRole);aStream>>zhiLiang;//固井质量,QStringindex=theModel->index(i,4);aItem=theModel->itemFromIndex(index);aItem->setData(zhiLiang,Qt::DisplayRole);aStream>>quYang;//boolindex=theModel->index(i,5);aItem=theModel->itemFromIndex(index);if (quYang)aItem->setCheckState(Qt::Checked);elseaItem->setCheckState(Qt::Unchecked);}aFile.close();return true;
}
void MainWindow::resetTable(int aRowCount)
{ //表格复位,先删除所有行,再设置新的行数,表头不变
//    QStringList     headerList;
//    headerList<<"测深(m)"<<"垂深(m)"<<"方位(°)"<<"总位移(m)"<<"固井质量"<<"测井取样";
//    theModel->setHorizontalHeaderLabels(headerList); //设置表头文字theModel->removeRows(0,theModel->rowCount()); //删除所有行theModel->setRowCount(aRowCount);//设置新的行数QString str=theModel->headerData(theModel->columnCount()-1,Qt::Horizontal,Qt::DisplayRole).toString();for (int i=0;i<theModel->rowCount();i++){ //设置最后一列QModelIndex index=theModel->index(i,FixedColumnCount-1); //获取模型索引QStandardItem* aItem=theModel->itemFromIndex(index); //获取itemaItem->setCheckable(true);aItem->setData(str,Qt::DisplayRole);aItem->setEditable(false); //不可编辑}
}

读取 stm 文件的数据之前必须设置 QDataStream 的流版本号,应该等于或高于数据保存时的流版本号。文件最早的两个数据时表格的行数和列数,读出这两个数据,就能知道数据的行数和列数,并调用自定义函数 resetTable()给数据模型复位,并设置其行数。

使用 QDataStream 的流操作方式读写文件的特点如下:

  • 读写操作都比较方便,支持读写各种数据类型,包括Qt的一些类,还可以为流数据读写扩展自定义的数据类型。读写某种类型的数据时,只要是流支持即可,而在文件内部是如何存储的,用户无需关心,由Qt预定义。
  • 写文件和读文件时必须保证使用的流版本兼容,即流的版本号相同,或读取文件的流版本号高于写文件时的流版本号。这是因为在不同的流版本中,流支持的数据类型的读写方式可能有所改变,必须保证读写版本的兼容。
  • 用这种方式保存文件时,写入数据采用Qt预定义的编码,即写入文件的二进制编码是由Qt预定义的,写多少个字节、字节是什么样的顺序,用户是不知道的。如果是由QDataStream读取数据,只需按类型读出即可。但是,如果由这种方法创建的文件是用于交换的,需要用其他的编程语言(如Matlab)来读取文件内容,则存在问题了。因为其他语言并没有与Qt的流写入完全一致的流读出功能,例如,其他语言并不知道Qt保存的QString或 QFon的内容是如何组织的。

标准编码文件的读写

保存为 dat 文件

前面采用 Qt 预定义的 stm 文件,这种方法使用简单,但是文件的格式不完全透明,不能创建用于交换的通用格式文件。

创建通用格式文件的方法是以标准编码方式创建文件,使文件的每个字节都有具体的定义。用户在读取这种文件时,按照文件格式定义读取出每个字节数据并做解析即可,不管使用什么编程语言都可以编写读写文件的程序。

主窗口工具栏上“保存 dat 文件“按钮将表格中的数据保存为标准编码文件,文件后缀是”.dat“。保存 dat 文件的代码是:

void MainWindow::on_actSaveBin_triggered()
{//保存二进制文件QString curPath=QDir::currentPath();//调用打开文件对话框选择一个文件QString aFileName=QFileDialog::getSaveFileName(this,tr("选择保存文件"),curPath,"二进制数据文件(*.dat)");if (aFileName.isEmpty())return; //if  (saveBinaryFile(aFileName)) //保存为流数据文件QMessageBox::information(this,"提示消息","文件已经成功保存!");
}
bool MainWindow::saveBinaryFile(QString &aFileName)
{ //保存为纯二进制文件QFile aFile(aFileName);  //以文件方式读出if (!(aFile.open(QIODevice::WriteOnly)))return false;QDataStream aStream(&aFile); //用文本流读取文件
//    aStream.setVersion(QDataStream::Qt_5_9); //无需设置数据流的版本aStream.setByteOrder(QDataStream::LittleEndian);//windows平台
//    aStream.setByteOrder(QDataStream::BigEndian);//QDataStream::LittleEndianqint16  rowCount=theModel->rowCount();qint16  colCount=theModel->columnCount();aStream.writeRawData((char *)&rowCount,sizeof(qint16)); //写入文件流aStream.writeRawData((char *)&colCount,sizeof(qint16));//写入文件流//获取表头文字QByteArray  btArray;QStandardItem   *aItem;for (int i=0;i<theModel->columnCount();i++){aItem=theModel->horizontalHeaderItem(i); //获取表头itemQString str=aItem->text(); //获取表头文字btArray=str.toUtf8(); //转换为字符数组aStream.writeBytes(btArray,btArray.length()); //写入文件流,长度uint型,然后是字符串内容}//获取数据区文字,qint8   yes=1,no=0; //分别代表逻辑值 true和falsefor (int i=0;i<theModel->rowCount();i++){aItem=theModel->item(i,0); //测深qint16 ceShen=aItem->data(Qt::DisplayRole).toInt();//qint16类型aStream.writeRawData((char *)&ceShen,sizeof(qint16));//写入文件流aItem=theModel->item(i,1); //垂深qreal chuiShen=aItem->data(Qt::DisplayRole).toFloat();//qreal 类型aStream.writeRawData((char *)&chuiShen,sizeof(qreal));//写入文件流aItem=theModel->item(i,2); //方位qreal fangWei=aItem->data(Qt::DisplayRole).toFloat();aStream.writeRawData((char *)&fangWei,sizeof(qreal));aItem=theModel->item(i,3); //位移qreal weiYi=aItem->data(Qt::DisplayRole).toFloat();aStream.writeRawData((char *)&weiYi,sizeof(qreal));aItem=theModel->item(i,4); //固井质量QString zhiLiang=aItem->data(Qt::DisplayRole).toString();btArray=zhiLiang.toUtf8();aStream.writeBytes(btArray,btArray.length()); //写入长度,uint,然后是字符串
//        aStream.writeRawData(btArray,btArray.length());//对于字符串,应使用writeBytes()函数aItem=theModel->item(i,5); //测井取样bool quYang=(aItem->checkState()==Qt::Checked); //true or falseif (quYang)aStream.writeRawData((char *)&yes,sizeof(qint8));elseaStream.writeRawData((char *)&no,sizeof(qint8));}aFile.close();return true;
}
  • 字节序:需要用 setByteOrder()函数指定字节序,并且与写入文件时用的字节序一致。
  • writeRawData() 函数:
  • writeBytes() 函数:在将字符串数据写入文件时,使用的是 writeBytes() 函数,而不是 writeRawData(),writeBytes() 函数的原型定义为 QDataStream &DataStream::writeBytes(const char *s, uint len)其中参数 s 是一个指向字节型数据的指针,len 是字节数据的长度 。writeBytes()在写入数据时,会先将 len 作为一个 quint32 类型写入数据流,然后在写入 len 个从指针 s 获取的数据。writeBytes()适合于写入字符串数据,因为在写入字符串之前要先写入字符串的长度,这样在读取文件时,就能知道字符串的长度,以便正确读取字符串。

读取 dat 文件

对于保存的 dat 文件,主窗口的“打开 dat 文件”可以打开保存的 dat 文件,下面是打开 dat 文件的代码:

void MainWindow::on_actOpenBin_triggered()
{//打开二进制文件QString curPath=QDir::currentPath();//系统当前目录QString aFileName=QFileDialog::getOpenFileName(this,tr("打开一个文件"),curPath,"二进制数据文件(*.dat)");if (aFileName.isEmpty())return; //if  (openBinaryFile(aFileName)) //保存为流数据文件QMessageBox::information(this,"提示消息","文件已经打开!");
}
bool MainWindow::openBinaryFile(QString &aFileName)
{//打开二进制文件QFile aFile(aFileName);  //以文件方式读出if (!(aFile.open(QIODevice::ReadOnly)))return false;QDataStream aStream(&aFile); //用文本流读取文件
//    aStream.setVersion(QDataStream::Qt_5_9); //设置数据流的版本aStream.setByteOrder(QDataStream::LittleEndian);
//    aStream.setByteOrder(QDataStream::BigEndian);qint16  rowCount,colCount;aStream.readRawData((char *)&rowCount, sizeof(qint16));aStream.readRawData((char *)&colCount, sizeof(qint16));this->resetTable(rowCount);//获取表头文字,但是并不利用char *buf;uint strLen;  //也就是 quint32for (int i=0;i<colCount;i++){aStream.readBytes(buf,strLen);//同时读取字符串长度,和字符串内容QString str=QString::fromLocal8Bit(buf,strLen); //可处理汉字}//获取数据区数据QStandardItem   *aItem;qint16  ceShen;qreal  chuiShen;qreal  fangWei;qreal  weiYi;QString  zhiLiang;qint8   quYang; //分别代表逻辑值 true和falseQModelIndex index;for (int i=0;i<rowCount;i++){aStream.readRawData((char *)&ceShen, sizeof(qint16)); //测深index=theModel->index(i,0);aItem=theModel->itemFromIndex(index);aItem->setData(ceShen,Qt::DisplayRole);aStream.readRawData((char *)&chuiShen, sizeof(qreal)); //垂深index=theModel->index(i,1);aItem=theModel->itemFromIndex(index);aItem->setData(chuiShen,Qt::DisplayRole);aStream.readRawData((char *)&fangWei, sizeof(qreal)); //方位index=theModel->index(i,2);aItem=theModel->itemFromIndex(index);aItem->setData(fangWei,Qt::DisplayRole);aStream.readRawData((char *)&weiYi, sizeof(qreal)); //位移index=theModel->index(i,3);aItem=theModel->itemFromIndex(index);aItem->setData(weiYi,Qt::DisplayRole);aStream.readBytes(buf,strLen);//固井质量zhiLiang=QString::fromLocal8Bit(buf,strLen);index=theModel->index(i,4);aItem=theModel->itemFromIndex(index);aItem->setData(zhiLiang,Qt::DisplayRole);aStream.readRawData((char *)&quYang, sizeof(qint8)); //测井取样index=theModel->index(i,5);aItem=theModel->itemFromIndex(index);if (quYang==1)aItem->setCheckState(Qt::Checked);elseaItem->setCheckState(Qt::Unchecked);}aFile.close();return true;
}
  • 字节序:在流创建后,需要用 setByteOrder()函数指定字节序,并且与写入文件时用的字节序一致。
  • readRawData() 函数:在读取基本类型的数据时,使用 QDataStream 的 readRawData() 函数,该函数原型为 int QDataStream::readRawData(char* s, int len),他会读取 len 个字节的数据,并且保存到指针 s 指向的存储区。例如:
qint16 rowCount;
aStream.readRawData((char*)& rowCount, sizeof(qint16);
  • readBytes() 函数:读取字符串时使用 readByres() 函数时,会自动读取前 4 个字节数据作为 quint32 的数据,并复制给 len 参数,因为 len 是引用方式传递的参数,所以,len 返回读取的数据的字节数。然后根据 len 的大小读取相应字节的数据,存储到指针 s 指向的存储区。
    参考资料:https://it.0voice.com

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

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

相关文章

【AI技术】PaddleSpeech部署方案

【AI技术】PaddleSpeech部署方案 技术介绍优点缺点 部署基础环境的搭建分步详解国内镜像源切换所需环境1 g所需环境2 vim所需环境3 cuda所需环境4 cudnn所需环境5 ssl源码拉取PaddleSpeech环境安装 部署文件分享DockerHub 技术介绍 PaddleSpeech是飞浆平台的一款TTS框架。 优…

【Python无敌】在 QGIS 中使用 Python

QGIS 中有 Python 的运行环境,可以很好地执行各种任务。 这里的问题是如何在 Jupyter 中调用 QGIS 的功能。 首先可以肯定的是涉及到 GUI 的一些任务是无法在 Jupyter 中访问的, 这样可以用的功能主要是地处理工具。 按如下方式进行了尝试。 原想使用 gdal:hillshade ,但是…

ARXML汽车可扩展标记性语言规范讲解

ARXML: Automotive Extensible Markup Language &#xff08;汽车可扩展标记语言&#xff09; xmlns: Xml name space &#xff08;xml 命名空间&#xff09; xsd: Xml Schema Definition (xml 架构定义) 1、XML与HTML的区别&#xff0c;可扩展。 可扩展&#xff0c;主要是…

flink实战 -- flink SQL 实现列转行

在 SQL 任务里面经常会遇到一列转多行的需求,下面就来总结一下在 Flink SQL 里面如何实现列转行的,先来看下面的一个具体案例. 需求 原始数据格式如下: namedatatest[{"content_type":"flink","url":"111"},{"content_type&quo…

游戏引擎学习第六天

这节讲的内容比较多: 参考视频:https://www.bilibili.com/video/BV1apmpYVEQu/ XInput 是微软提供的一个 API&#xff0c;用于处理 Windows 平台上 Xbox 控制器&#xff08;包括有线和无线&#xff09;及其他游戏控制器的输入。它为开发者提供了一组函数&#xff0c;用于查询控…

vivado+modelsim: xxx is not a function name

xxx is not a function name vivado问题:xxx is not a function name原因 vivado问题:xxx is not a function name 在写verilog modelsim仿真时&#xff0c;遇到error&#xff1a;xxx is not a function name。 原因 该变量xxx在仿真文件里&#xff0c;如下图红框所示&#…

云计算在教育领域的应用

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 云计算在教育领域的应用 云计算在教育领域的应用 云计算在教育领域的应用 引言 云计算概述 定义与原理 发展历程 云计算的关键技…

基于STM32设计的森林火灾监测系统(华为云IOT)_263

文章目录 一、前言1.1 项目介绍【1】项目开发背景【2】设计实现的功能【3】项目硬件模块组成【4】设计意义【5】国内外研究现状【6】摘要1.2 设计思路1.3 系统功能总结1.4 开发工具的选择【1】设备端开发【2】上位机开发1.5 参考文献1.6 系统框架图1.7 系统原理图1.8 实物图1.9…

立体工业相机提升工业自动化中的立体深度感知

深度感知对仓库机器人应用至关重要&#xff0c;尤其是在自主导航、物品拾取与放置、库存管理等方面。 通过将深度感知与各种类型的3D数据&#xff08;如体积数据、点云、纹理等&#xff09;相结合&#xff0c;仓库机器人可以在错综复杂环境中实现自主导航&#xff0c;物品检测…

模拟鼠标真人移动轨迹算法-易语言

一.简介 鼠标轨迹算法是一种模拟人类鼠标操作的程序&#xff0c;它能够模拟出自然而真实的鼠标移动路径。 鼠标轨迹算法的底层实现采用C/C语言&#xff0c;原因在于C/C提供了高性能的执行能力和直接访问操作系统底层资源的能力。 鼠标轨迹算法具有以下优势&#xff1a; 模拟…

高级java每日一道面试题-2024年11月04日-Redis篇-Redis如何做内存优化?

如果有遗漏,评论区告诉我进行补充 面试官: Redis如何做内存优化? 我回答: 在Java高级面试中&#xff0c;关于Redis如何做内存优化的问题&#xff0c;可以从以下几个方面进行详细解答&#xff1a; 一、Redis内存优化概述 Redis内存优化主要是指通过一系列策略和技术&#…

JavaWeb——Web入门(8/9)- Tomcat:基本使用(下载与安装、目录结构介绍、启动与关闭、可能出现的问题及解决方案、总结)

目录 基本使用内容 下载与安装 目录结构介绍 启动与关闭 启动 关闭 可能出现的问题及解决方案 问题一&#xff1a;启动时窗口一闪而过 问题二&#xff1a;端口号冲突 问题三&#xff1a;部署应用程序 总结 基本使用内容 Tomcat 服务器在 Java Web 开发中扮演着至关重…

PostgreSQL中如果有Left Join的时候索引怎么加

在PostgreSQL中&#xff0c;当你的查询包含多个LEFT JOIN和WHERE条件时&#xff0c;合理地添加索引可以显著提高查询性能。以下是一些具体的优化步骤和建议&#xff1a; 1. 分析查询 使用 EXPLAIN ANALYZE 命令分析你的查询&#xff0c;了解查询的执行计划&#xff0c;识别出连…

W3C HTML 活动

关于W3C&#xff08;万维网联盟&#xff09;的HTML活动&#xff0c;我们可以从HTML的不同版本的发展历程中了解其主要的活跃时期和贡献。 HTML 2.0&#xff1a;这个版本的HTML是由Internet工程工作小组&#xff08;IETF&#xff09;的HTML工作组于1996年开发的。它是HTML的早期…

UE5-----MenuSystem

在 UE5 中&#xff0c;如果你看到一个名为 AMenuSystemCharacter 的类&#xff0c;它很可能是开发者为了特定目的而创建的一个自定义角色类。通常&#xff0c;这样的类会继承自 ACharacter 或其他相关类&#xff0c;并且可能包含以下功能或特性&#xff1a; UI交互&#xff1a…

通过DNS服务器架构解释DNS请求过程

在前面的章节,这里,基于PCAP数据包和RFC文档详细介绍了DNS请求和响应的每个字段的含义。但是在现实的网络世界中,DNS请求和响应的数据包是怎么流动的,会经过哪些设备。本文将着重说明一下目前网络空间中DNS请求和响应的流动过程。 当前网络空间中比较常见DNS请求的流程如下…

如何利用静态住宅IP优化Facebook商城的网络稳定性与运营效率

在如今的电商时代&#xff0c;Facebook已经成为全球商家不可忽视的平台&#xff0c;特别是在构建Facebook商城、推广广告以及与客户互动时&#xff0c;稳定且高效的网络连接显得尤为重要。作为一个在Facebook上经营商城的商家&#xff0c;确保广告投放顺利进行、账户安全不受威…

Java 之 XMLStreamConstants 原理及使用详细介绍

目录 引言 XMLStreamConstants 接口常量 详细解释 使用示例 示例XML文档 示例代码 输出 总结 引言 在Java中&#xff0c;处理XML文档是一个常见的任务。StAX&#xff08;Streaming API for XML&#xff09;是一种高效的XML解析方式&#xff0c;它提供了一种基于事件的…

aspose如何获取PPT放映页“切换”的“持续时间”值

aspose如何获取PPT放映页“切换”的“持续时间”值 项目场景问题描述问题1&#xff1a;从官方文档和资料查阅发现并没有对切换的持续时间进行处理的方法问题2&#xff1a;aspose的依赖包中&#xff0c;所有的关键对象都进行了混淆处理 解决方案1、找到ppt切换的持续时间对应的混…

GIT:如何查找已删除的文件的历史记录

首先你得知道文件的名称和路径 然后打开 gitlab&#xff0c;到项目中&#xff0c;仓库-> 文件 查找文件 复制文件名到可能存在过这个文件的分支当中&#xff0c;就能看到了