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

【C++】C++ 中的 IO 流

文章目录

  • 一、C语言的输入输出
  • 二、什么是流
  • 三、C++ IO 流
    • 1、C++ 标准 IO 流
    • 2、C++ 文件 IO 流
  • 四、stringstream 介绍

一、C语言的输入输出

在C语言中我们使用最频繁的输入输出方式是 scanf () 与 printf()

  • scanf():从标准输入设备 (键盘) 读取数据,并将值存放在变量对应的内存空间中。
  • printf():将指定的文字/字符串输出到标准输出设备 (显示器)。(注意宽度输出和精度输出控制)

实际上C语言借助了相应的缓冲区来进行输入与输出。如下图所示:image-20230530150415762

对输入输出缓冲区的理解

  • 缓冲区的存在可以屏蔽掉低级I/O的实现;由于低级I/O的实现依赖操作系统本身内核的实现,所以如果能够屏蔽这部分的差异,就可以很容易写出可移植的程序。

  • 可以使用这部分的内容实现 “行” 读取的行为;对于计算机而言是没有 “行” 这个概念,有了这部分,我们就可以定义 “行” 的概念,然后解析缓冲区的内容,返回一个 “行”。

注:C语言除了有输入输出接口 scanf 和 printf,还有文件操作读写接口 fread/fwrite、fscanf/fprintf,以及字符串序列化反序列化接口 sprintf/snprintf/sscanf。


二、什么是流

“流” 即是流动的意思,是物质从一处向另一处流动的过程,是对一种有序连续且具有方向性的数据( 其单位可以是bit/byte/packet )的抽象描述流的特点是有序连续且具有方向性

C++流是指信息从外部输入设备(如键盘)向计算机内部(如内存)输入和从内存向外部输出设备(显示器)输出的过程。这种输入输出的过程被形象的比喻为 “流”

为了实现这种流动,C++定义了I/O标准类库,这些每个类都称为流/流类,用以完成某方面的功能。


三、C++ IO 流

C++系统实现了一个庞大的 I/O 标准类库,其中ios为基类,其他类都是直接或间接派生自ios类image-20230530142534344

1、C++ 标准 IO 流

C++标准库提供了4个全局流对象cin、cout、cerr、clog:

  • cin:进行标准输入,即数据通过键盘输入到程序中。
  • cout:进行标准输出,即数据从内存流向控制台 (显示器)。
  • cerr:进行标准错误的输出。
  • clog:进行日志的输出。

从 I/O 标准类库的继承体系图中可以看出,cout、cerr、clog 是 ostream 类的三个不同的对象,因此这三个对象基本没有区别,只是应用场景不同而已。

注:在使用这些全局对象流时必须要包含文件并引入std标准命名空间。

在使用 cin/cout 标准输入输出时有如下注意事项

  • cin为缓冲流。用户从键盘输入的数据会保存在输入缓冲区中,当要提取时,cin 是从输入缓冲区中取数据;如果数据一次输入过多,则会暂存在缓冲区中,等待被读取。如果数据输出错误,则必须在 enter 之前 Backspace 并修改,如果回车键按下就无法挽回了,只能等待 cin 将输入缓冲区中的数据读取完毕后,才要求输入新的数据。

  • 用户输入的数据类型必须与要提取的数据类型一致,否则就会出错。但出错只是在流的状态字 state 中将对应位置位 (置1),程序并不会被终止。

  • 和C语言输入规则一样,空格和回车都可以作为数据之间的分格符,所以多个数据可以在一行输入,也可以分行输入。但如果是字符型和字符串,则空格无法用 cin 输入,因为其会被识别为数据分隔符,需要使用 getline 函数。

流插入和流提取运算符的重载

cin 和 cout 之所以可以直接输入和输出内置类型数据,是因为标准库已经将所有内置类型的输入和输出全部重载了image-20230530144455378image-20230530144523549

所以对于自定义类型来说,如果我们想让其支持 cin/cout 标准输入输出,就需要手动重载 >> 和 << 运算符。需要注意的是,自定义类型在重载流插入和流提取运算符时,需要先将 operator<< 和 operator>> 声明为类的友元函数,然后再在类外对函数进行定义,至于原因我们在 类和对象下篇 中有详细介绍,不清楚的同学可以看一看。

下面我们给出日期类输入输出重载的例子:

class Date
{//输入输出重载--友元函数friend ostream& operator << (ostream& out, const Date& d);friend istream& operator >> (istream& in, Date& d);
public:Date(int year = 1, int month = 1, int day = 1):_year(year), _month(month), _day(day){}private:int _year;int _month;int _day;
};istream& operator >> (istream& in, Date& d)
{in >> d._year >> d._month >> d._day;return in;
}ostream& operator << (ostream& out, const Date& d)
{out << d._year << " " << d._month << " " << d._day;return out;
}

image-20230530150011137

类的上下文转换

C++中的类的上下文转换指的是在特定的上下文环境中,将对象或表达式隐式地转换为其他类型。这种转换是由编译器自动进行的,不需要从代码中显式地进行调用。常见的上下文转换包括:

  • 数值类型之间的转换:当将一个整数类型赋给一个较小的整数类型、或者将一个浮点类型赋给一个整数类型时,编译器会自动转换数据类型。
  • 派生类向基类的转换:派生类对象可以转换为基类对象的指针或引用,这样可以使得派生类对象使用基类的成员函数和成员变量。
  • 用户定义的类型转换:通过将类定义为带有类型转换运算符的类,可以对用户自定义的类型进行转换。

数值类型转换和派生类基类转换我们之前都已经学习过了,今天我们来学习用户定义类型转换。下面我通过一个例子来引入。

我们平时在做 OJ 题的时候,特别是 ACM 模式的 OJ 题,对于IO类型的算法,一般都需要循环输入,如下:

// 单个元素循环输入--元素为内置类型
while (cin >> a)
{// ...
}// 多个元素循环输入
while (c >> a >> b >> c)
{// ...
}// 整行接收--元素为string类型
while (cin >> str)
{// ...
}

可以看到,我们的案例中包含了 string 类型;但是我们又发现,string 类中重载的流提取运算符 operator>> 的返回值是 istream 类型的对象。image-20230530163751842

那么问题来了,我们平时只有三种类型的数据能够用来作为逻辑判断:

  1. 整形:非0代表真,0代表假。
  2. 指针类型:非空代表真,nullptr 代表假。
  3. bool 类型:true 代表真,false 代表假。

而 istream 作为自定义类型的对象如何能够作为逻辑判断的条件呢?答案是 istream 类内部重载了 bool:image-20230530164451456

综上,由于 istream 类中重载了流提取运算符,所以当我们使用 while (cin >> str)去流中提取对象数据时,调用的是 operator>>,该函数返回一个 istream类型的对象;同时,因为 istream 类中还重载了 bool,所以 istream 对象会去调用 operator bool函数;operator bool 调用时如果接收流失败,或者有结束标志,返回 false,否则返回 true;所以这里自定义类型 istream 的对象可以用作逻辑条件值

注:在需要 bool 类型的地方,比如条件判断处,编译器会自动调用 operator bool函数,将自定义类型转化为 bool 类型。同时,operator bool函数被 explicit关键字修饰,这是防止隐式地将一个类对象转换成 bool 类型,从而在条件判断上造成误解。

我们也可以在我们自己的自定义类中重载 operator>>operator bool,从而让其支持进行作为逻辑判断值:

class Date
{friend ostream& operator << (ostream& out, const Date& d);friend istream& operator >> (istream& in, Date& d);
public:Date(int year = 1, int month = 1, int day = 1):_year(year), _month(month), _day(day){}operator bool(){//这里的条件是随意写的,假设输入_year为0,则结束if (_year == 0)return false;elsereturn true;}private:int _year;int _month;int _day;
};istream& operator >> (istream& in, Date& d)
{in >> d._year >> d._month >> d._day;return in;
}ostream& operator << (ostream& out, const Date& d)
{out << d._year << " " << d._month << " " << d._day;return out;
}int main()
{//自动识别类型的本质--函数重载//内置类型可以直接使用--因为库里面ostream类型已经实现了//string类型也可以直接使用,因为其内部也重载了,但其他自定义类型不行int i = 1;double j = 2.2;string s("abcdef");cout << i << endl;cout << j << endl;cout << s << endl;//自定义类型则需要我们自己重载<< 和 >>//如果要让自定义类型对象能够作为逻辑判断值,还需要重载bool、int等运算符Date d(2023, 5, 30);cout << d << endl;while (d){cin >> d;cout << d << endl;}return 0;
}

image-20230530170738142

注意:并不是一定要重载 bool 类对象才能作为逻辑条件值,重载整形、指针类型都可以,因为它们都能够进行逻辑判断。同时,operator bool其本质是通过重载将自定义类型转化为内置类型,它的使用可以不仅仅局限于用作逻辑条件值,也可以用作其他地方。image-20230530171310558


2、C++ 文件 IO 流

C++ 中一共有三个用于文件操作的类 ifstream/ofstream/fstream,如下:

  • ifstream – 输入文件流,仅用作输入用;
  • ofstream – 输出文件流,仅用作输出用;
  • fstream – 文件流,用作输入输出。

这三个类的关系如图:image-20230530142534344

下面我们以 fstream 类为例来解释 C++ 中面向对象的文件操作,其他两个类的使用和 fstream 类的使用基本一样。

构造函数

fstream 支持无参构造和带参构造,不支持拷贝构造,支持移动构造:

  • 无参构造:创建一个未与任何文件关联的流对象,即不会打开任何文件。当使用默认构造函数创建 fstream 对象时,我们需要使用 open 函数来让对象与一个文件相关联。image-20230530175701243

  • 带参构造:需要指定要打开的文件名以及文件的打开方式;如果要以多种方式打开,则需要使用 | 运算符。C++ 文件的打开方式如下:其中 in/out 表示该对象对文件进行读/写操作,binary/ate/app/trunc 分别表示向文件中读取/写入数据的格式 – 二进制读取或写入/文件尾写入/追加写入/写入前清空文件内容。image-20230530180353651

    特别注意:fstream 默认情况下以只读形式打开文件,以文本格式向文件中读取和写入数据。同时,文件对象在析构时会自动调用 close 成员函数关闭文件;当然,我们也可以手动调用 close 来关闭文件


文件操作相关成员函数

我们可以使用流提取和流插入运算符对文件进行读写操作,或使用成员函数进行读写。

需要注意的是,虽然 ifstream/ofstream/fstream 类中提供了非常丰富的成员函数来让我们对文件进行操作:image-20230530173409565

但是这些接口在实际开发中其实用的最多的还是 operator<<operator>>,其他接口都用的很少,包括 read 和 write 接口。这是因为operator<<operator>>使用起来非常方便,通过这两个接口向文件中读取和写入数据就和我们向标准输入输出中写入读出数据一样 – cin 从文件/标准输入读取数据,cout 向文件/标准输出写入数据 (其实本质上标准输入输出也是文件,或者是流)

下面是 C++ 面向对象文件操作的一个示例:

struct ServerInfo
{char _address[32];int _port;Date _date;
};struct ConfigManager
{
public:ConfigManager(const char* filename):_filename(filename){}void WriteBin(const ServerInfo& info){ofstream ofs(_filename, ios_base::out | ios_base::binary);ofs.write((const char*)&info, sizeof(info));}void ReadBin(ServerInfo& info){ifstream ifs(_filename, ios_base::in | ios_base::binary);ifs.read((char*)&info, sizeof(info));}//C++文件流的优势就是可以对内置类型和自定义类型,都使用一样的方式,去流插入和流提取数据//但是需要自定义类型Date重载了>> 和 <<void WriteText(const ServerInfo& info){//默认以文本格式向文件中读取和写入数据ofstream ofs(_filename);//这里可以调用成员函数write,但是<<运算符更方便ofs << info._address << " " << info._port << " " << info._date;}void ReadText(ServerInfo& info){ifstream ifs(_filename);ifs >> info._address >> info._port >> info._date;}private:string _filename; // 配置文件
};int main()
{ServerInfo winfo = { "192.0.0.1", 80, { 2023, 5, 30 } };// 二进制读写ConfigManager cf_bin("test.bin");cf_bin.WriteBin(winfo);ServerInfo rbinfo;cf_bin.ReadBin(rbinfo);cout << rbinfo._address << " " << rbinfo._port << " " << rbinfo._date << endl;// 文本读写ConfigManager cf_text("test.text");cf_text.WriteText(winfo);ServerInfo rtinfo;cf_text.ReadText(rtinfo);cout << rtinfo._address << " " << rtinfo._port << " " << rtinfo._date << endl;return 0;
}

image-20230530183718145

注意:如果文件是以二进制格式打开的,则不能直接向文件中写入 string 对象;因为 string 是自定义类型,其中除了有 char* _str字符数组之外,还有很多其他成员变量和成员函数,若直接将其写入到文件中,那么写入的数据就是该对象所占用的内存空间,即对象中成员变量和成员函数的地址,而不是字符串本身的内容,即 _str 变量指向的堆空间中的字符数组。这样,在读取文件时,就无法正确地获取原始字符串数据 (下次进行读取时该对象可能已经被销毁,再通过旧对象中成员变量的地址去访问堆上的字符数组会造成野指针访问)。

以文本格式打开的文件可以直接向其中写入 string 对象;因为在文本文件中,数据是按照字符编码的形式存储的,即将单个字符转换成相应的数字形式后再存储到文件中,即将堆空间中字符数组对应的 ASCII 值写入到文件。因此,字符串数据可以直接以文本形式写入到文件中,并在读取时直接通过 >> 运算符等操作进行读取。


四、stringstream 介绍

在C语言中,如果想要将内置类型/结构体类型的数据转化为字符串格式,通常是使用 sprintf/snprintf 函数,但是这两个函数在使用时需要先给出保存结果的空间,而空间要给多大,是不好界定的。并且当转化格式不匹配时,还可能会得到错误的结果甚至程序直接崩溃。

C++ 提供了 stringstream 类来解决这个问题。stringstream 包含在 <sstream> 头文件中,该头文件下主要有三个类:istringstream、ostringstream 和 stringstream,分别用来进行流的输入、输出和输入输出操作,本文主要介绍 stringstream。image-20230530202421296

stringstream 主要有以下用途:

  1. 将数值类型数据格式化为字符串。

    #include<sstream>
    int main()
    {int a = 12345678;string sa;// 将一个整形变量转化为字符串,存储到string类对象中stringstream s;s << a;s >> sa;cout << sa << endl;// clear()// 注意多次转换时,必须使用clear将上次转换状态清空掉// stringstreams在转换结尾时(即最后一个转换后),会将其内部状态设置为badbit// 因此下一次转换是必须调用clear()将状态重置为goodbit才可以转换// 但是clear()不会将stringstreams底层字符串清空掉// s.str("");// 将stringstream底层管理string对象设置成"",// 否则多次转换时,会将结果全部累积在底层string对象中s.str("");s.clear();  // 清空s, 不清空会转化失败double d = 12.34;s << d;s >> sa;string sValue;sValue = s.str();  // str()方法:返回stringsteam中管理的string类型cout << sValue << endl;return 0;
    }
    

    image-20230530202843448

  2. 字符串拼接。

    int main()
    {stringstream sstream;// 将多个字符串放入 sstream 中sstream << "first" << " " << "string,";sstream << " second string";cout << "strResult is: " << sstream.str() << endl;// 清空 sstreamsstream.str("");sstream << "third string";cout << "After clear, strResult is: " << sstream.str() << endl;return 0;
    }
    

    image-20230530203024713

  3. 序列化和反序列化结构数据。

    struct ChatInfo
    {string _name; // 名字int _id;      // idDate _date;   // 时间string _msg;  // 聊天信息
    };int main()
    {// 结构信息序列化为字符串ChatInfo winfo = { "张三", 135246, { 2022, 4, 10 }, "晚上一起看电影吧" };//将结构数据序列化到stringstream对象中ostringstream oss;oss << winfo._name << " " << winfo._id << " " << winfo._date << " " << winfo._msg;//将stringstream中的字符串反序列化到string对象中或直接输出string str = oss.str();cout << str << endl << endl;// 我们通过网络这个字符串发送给对象,实际开发中,信息相对更复杂,// 一般会选用Json、xml等方式进行更好的支持// 字符串解析成结构信息ChatInfo rInfo;istringstream iss(str);iss >> rInfo._name >> rInfo._id >> rInfo._date >> rInfo._msg;cout << "-------------------------------------------------------" << endl;cout << "姓名:" << rInfo._name << "(" << rInfo._id << ") ";cout << rInfo._date << endl;cout << rInfo._name << ":>" << rInfo._msg << endl;cout << "-------------------------------------------------------" << endl;return 0;
    }
    

    image-20230530203406652

    需要注意的是:

    • 序列化和反序列化操作在网络中非常重要,它用于在不同的计算机之间传输数据。
    • 比如当客户端需要向服务器发送一个请求时,它需要将请求数据序列化为字节流并通过网络传输到服务器。在服务器端接收到请求后,需要对接收到的字节流进行反序列化操作,获得原始的请求数据,从而能够获取客户端请求的具体信息并做出相应的响应。
    • C++ 提供的 stringstream 虽然可以完成序列化与反序列化操作,但是它只适用于小型对象的序列化和反序列化操作。如果需要处理大量的数据,或者需要进行高性能的序列化和反序列化操作,则需要更加专业化的序列化库,比如 Json 和 protobuf,这些我们将在 Linux 网络编程部分进行学习。

stringstream 有如下注意事项:

  • stringstream 实际是在其底层维护了一个 string 类型的对象用来保存结果。
  • 多次进行数据类型转化时,一定要用 clear() 来清空才能正确转化,但 clear() 不会将 stringstream 底层的 string 对象清空。
  • 可以使用 s. str(“”) 方法将底层 string 对象设置为 “空字符串”。
  • 可以使用 s.str() 让 stringstream 返回其底层的 string 对象。
  • stringstream 使用 string 类对象代替字符数组,可以避免缓冲区溢出的危险 (自动扩容),而且其会对参数类型进行推演,不需要格式化控制,也不会出现格式化失败的风险,因此使用更加方便和安全。

相关文章:

【C++】C++ 中的 IO 流

文章目录 一、C语言的输入输出二、什么是流三、C IO 流1、C 标准 IO 流2、C 文件 IO 流 四、stringstream 介绍 一、C语言的输入输出 在C语言中我们使用最频繁的输入输出方式是 scanf () 与 printf()&#xff1a; scanf()&#xff1a;从标准输入设备 (键盘) 读取数据&#xf…...

QFuture的使用

QFuture 是 Qt 提供的一个类&#xff0c;用于表示异步操作的返回值或状态。异步操作指的是那些不会阻塞主线程的操作&#xff0c;例如文件读写、网络请求、计算等等。 在执行异步操作时&#xff0c;可以使用 QtConcurrent 模块提供的函数 (QFuture<T> QtConcurrent::run…...

通过dockerfile将nginx、前端和后端封装成一个镜像

1、内容如下 2、dist文件 就是vue项目的打包文件 3、jar包文件 就是springboot的打包文件 4、编写Dockerfile #引用 jdk1.8作为基础镜像,这个jdk1.8是我自己用linux版本的jdk打包的,具体操作可以看 #https://blog.csdn.net/qq_38639813/article/details/129384923中将jd…...

如何利用CiteSpace快速锁定领域内最新研究热点并制作精美的可视化专题图?

【基于Citespace和vosviewer文献计量学相关论文 】 ​ 01 文献计量学方法与应用 1. 文献计量学方法基本介绍 2. 与其他综述方法区别联系 3. 各学科领域应用趋势近况 4. 主流分析软件优缺点对比 5. 经典高分10SCI思路复盘 6. 软件安装与Java环境配置 02 主题确定、数据检…...

嵌入式开发从入门到精通之第二十二节:蓝牙芯片CC254x ADC 电压测量

目录 1. CC254x ADC原理 参考电压 采样通道 采样率 采样时间...

北邮22信通:二叉树显示路径的两种方法 递归函数保存现场返回现场的实例

北邮22信通一枚~ 跟随课程进度每周更新数据结构与算法的代码和文章 持续关注作者 解锁更多邮苑信通专属代码~ 获取更多文章 请访问专栏~ 北邮22信通_青山如墨雨如画的博客-CSDN博客 一.讲解 要想实现二叉树的路径显示&#xff0c;我们要按照…...

vue 3 第二十八章:组件十二(组件的v-model、多v-model)

文章目录 1. 基本使用2. 使用conputed实现3. v-model 的参数4. 多 v-model 的使用5. v-model 修饰符 在 Vue 3 中&#xff0c; v-model 指令的使用更加灵活&#xff0c;可以绑定任意属性和事件。例如&#xff0c;我们可以使用 v-model:checked 指令来绑定单选框或复选框的 c…...

LCD 显示

概述 LCD显示控制模块接收 MCU 送过来的数据&#xff0c;按一定规律储存在显示 RAM 中&#xff0c;并根据显示 RAM 中的数据驱动 LCD 显示屏来实现期望的字符显示功能。 主要特点&#xff1a; ⚫ 最大支持 840 、 642 、 444 的显示段数 ⚫ 1/3bias 、 1/4bia s ⚫ 16 级灰度可…...

互联网医院开发|在线问诊系统架构设计功能有哪些?

互联网医院会增加更多的医疗业务&#xff0c;电话问诊、视频问诊、个性化的医疗套餐等&#xff0c;未来互联网医院会建成围绕健康主题的深度大数据平台和多元化医疗服务生态体系&#xff0c;丰富人工智能、物联网等应用场景&#xff0c;为用户提供更好的服务体验、更低的成本、…...

数据安全运营有效管理-数据安全复合治理框架和模型解读(1)

数据治理,数据安全治理行业在发展,在实践,所以很多东西是实践出来的,哪有什么神仙理论指导,即使有也是一家之说,但为了提高企业投产比,必要的认知是必须的,落地运营管理水平差异直接决定产品和项目是否可持续性,当前和未来更需要专业和有效创新。数据安全治理要充分考…...

【刷题之路】LeetCode 面试题 03.02. 栈的最小值

【刷题之路】LeetCode 面试题 03.02. 栈的最小值 一、题目描述二、解题1、方法1——“辅助栈”1.1、思路分析1.2、代码实现 一、题目描述 原题连接&#xff1a; 面试题 03.02. 栈的最小值 题目描述&#xff1a; 请设计一个栈&#xff0c;除了常规栈支持的pop与push函数以外&am…...

如何处理图片排重(精准排重,相似排重)

图片相似度对比 1、需求 假如有一个图片池&#xff0c;存有1亿图片。给一张目标图片&#xff0c;在图片池中做匹配。 判断一张图片是否在图片池中出现过。&#xff08;完全一样&#xff09;判断有没有相似的出现过。比如两张图相似度90&#xff0c;两张图片是在描述一件事情。 …...

盐城北大青鸟“北大青鸟杯”IT精英挑战赛设中心评审隆重开赛

为积极响应北大青鸟总部开展第十届“北大青鸟杯”全国IT精英挑战赛的号召&#xff0c;成就学员们的IT梦想&#xff0c;“北大青鸟杯”IT精英挑战赛&#xff08;设计组&#xff09;盐城卓晨中心评审于2023年5月25日下午1:00在人才大厦306教室正式开赛&#xff01; ​ 赛前&a…...

Pluma 插件管理框架

1. 概述 Pluma 是一个用 C 开发的可用于管理插件的开源架构&#xff0c;其官网地址为&#xff1a;http://pluma-framework.sourceforge.net/。该架构是个轻量级架构&#xff0c;非常易于理解。 Pluma 架构有以下基本概念&#xff1a; 1&#xff09;插件的外在行为体现为一个…...

Leetcode11 盛最多水的容器

Leetcode11 盛最多水的容器 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&#xff1a;https://leetcode.cn/problems/container-with-most-water/description 博主Github&#xff1a;https://github.com/GDUT-Rp/LeetCode 题目&#xff1a; 给定一个长度为 n…...

Java

FileOutputStream写数据的3种方式 void write(int b) //一次写一个字节的数据 void write(byte[] b) //一次写一个字节数组数据 void write(byte[] b, int off,int len) //一次写一个字节数组的部分数据 参数一:数组;参数二:起始索引 0;参数三:个数换行: windows:“\r\n” lin…...

第十四章行为性模式—策略模式

文章目录 命令模式解决的问题结构实例存在的问题适用场景 JDK源码解析 行为型模式用于描述程序在运行时复杂的流程控制&#xff0c;即描述多个类或对象之间怎样相互协作共同完成单个对象无法单独完成的任务&#xff0c;它涉及算法与对象间职责的分配。行为型模式分为类行为模式…...

Leaflet基本用法

使用 阿里云地理工具 获取相应的地理JSON数据&#xff0c;用于对地图边界绘制。 如何使用leaflet&#xff1f; 这里用HTML5进行操作&#xff1b; 因为我是用的是Leaflet库&#xff0c;所以要引入JavaScript 和 CSS 文件&#xff08;可参考官网https://leafletjs.com/&#x…...

Unity | HDRP高清渲染管线学习笔记:示例场景解析

目录 一、HDRP入门 1.HDRP设置 1.1 HDRP配置文件中的全部设置项 1.1.1 Rendering下的Lit Shader Mode 1.1.2 Lighting 下的Volumetrics&#xff08;体积光&#xff09;和Screen Space Reflection&#xff08;屏幕空间反射&#xff09; 2.离线渲染VS实时渲染 3.Volume组件 …...

【Netty】Netty 编码器(十三)

文章目录 前言一、MessageToByteEncoder 抽象类二、MessageToMessageEncoder 抽象类总结 前言 回顾Netty系列文章&#xff1a; Netty 概述&#xff08;一&#xff09;Netty 架构设计&#xff08;二&#xff09;Netty Channel 概述&#xff08;三&#xff09;Netty ChannelHan…...

Netty和Tomcat的区别、性能对比

文章目录 一、Netty和Tomcat有什么区别&#xff1f;二、为什么Netty受欢迎&#xff1f;三、Netty为什么并发高 &#xff1f; 一、Netty和Tomcat有什么区别&#xff1f; Netty和Tomcat最大的区别就在于通信协议&#xff0c;Tomcat是基于Http协议的&#xff0c;他的实质是一个基…...

chatgpt赋能python:Python函数调用局部变量-深入了解

Python函数调用局部变量-深入了解 函数调用局部变量是Python中的一个重要概念&#xff0c;特别是在大型项目中&#xff0c;其中多个函数共享相同变量时。在本文中&#xff0c;我们将深入探讨Python函数调用局部变量&#xff0c;并为您介绍一些实用技巧。 什么是Python函数调用…...

Android 12.0 NavigationBarView 导航栏 左边显示的修改

1.概述 在12.0定制化开发中,要求导航栏左边显示的定制化,这时需要了解导航栏的显示控制方向,然后修改显示方向 在10.0以后关于导航栏显示位置都是在DisplayPolicy.java中处理的所以查询相关的设置方法,然后修改导航栏显示方向2.NavigationBarView 导航栏 左边显示的修改的…...

Mybatis源码细节探究:二级缓存Cache对象是在什么时候创建的?

给自己的每日一句 不从恶人的计谋&#xff0c;不站罪人的道路&#xff0c;不坐亵慢人的座位&#xff0c;惟喜爱耶和华的律法&#xff0c;昼夜思想&#xff0c;这人便为有福&#xff01;他要像一棵树栽在溪水旁&#xff0c;按时候结果子&#xff0c;叶子也不枯干。凡他所做的尽…...

【数据库】无效数据:软件测试对无效数据的处理

目录 一、无效数据的常见场景 &#xff08;1&#xff09;测试阶段 &#xff08;2&#xff09;测试方法 二、无效数据的概念 三、无效数据的影响 四、无效数据的识别 五、无效数据的处理方法 &#xff08;1&#xff09;拒绝无效数据 ① 拒绝无效数据的概念 ② 拒绝…...

高精度电压源如何设计出来的

高精度电压源是一种用于提供高精度电压的电子设备&#xff0c;通常用于测量和控制系统。高精度电压源的设计是一个复杂的过程&#xff0c;需要考虑多个因素&#xff0c;包括电路设计、元件选型、测量误差、稳定性等。下面将从电路设计和元件选型两个方面&#xff0c;详细介绍高…...

混合属性mix-blend-mode不生效

下面的ABCDE是混合图层&#xff0c;box是他们的父级&#xff0c;一般浏览器支持都没什问题需要注意的是&#xff0c;确保父元素不是透明的&#xff0c; 我使用的时候发现给父元素rgba设置透明度这种方式没啥作用&#xff0c;还得是纯色&#xff0c;没去深究&#xff0c;设置纯色…...

测试计划编写说明

第1章 引言 1.1目的 简述本计划的目的,旨在说明各种测试阶段任务、人员分配和时间安排、工作规范等。 测试计划在策略和方法的高度说明如何计划、组织和管理测试项目。测试计划包含足够的信息使测试人员明白项目需要做什么是如何运作的。另外,清晰的文档结构能使任何一个读…...

Android 12.0Recent列表不显示某个app

1.概述 在12.0 的产品定制化开发中,在点击导航栏最近任务列表时,如果做到不显示某个app 呢 一种做法是在app中直接处理 一种做法是在framework中处理 接下来看这两种处理方法 1, app中处理 为该应用AndroidManifest xml文件中主MainActivity设置属性 android:excludeFromR…...

力扣sql中等篇练习(二十七)

力扣sql中等篇练习(二十七) 1 连续两年有3个及以上订单的产品 1.1 题目内容 1.1.1 基本题目信息 1.1.2 示例输入输出 1.2 示例sql语句 # Write your MySQL query statement below WITH T as (SELECT t.product_id,t.d,count(order_id) numFROM(SELECT order_id,product_id,…...