Unity XML3——XML序列化

一、XML 序列化

​ 序列化:把对象转化为可传输的字节序列过程称为序列化,就是把想要存储的内容转换为字节序列用于存储或传递

​ 反序列化:把字节序列还原为对象的过程称为反序列化,就是把存储或收到的字节序列信息解析读取出来使用

(一)XML 序列化

1.准备数据结构

public class Lesson1Test
{
    public    int          testPublic    = 10;
    private   int          testPrivate   = 11;
    protected int          testProtected = 12;
    internal  int          testInternal  = 13;
    public    string       testPUblicStr = "123";
    public    int          testPro { get; set; }
    public    Lesson1Test2 testClass = new Lesson1Test2();
    public    int[]        arrayInt  = new int[3] { 5, 6, 7 };
    
    public    List<int> listInt = new List<int>() { 1, 2, 3, 4 };
    
    public    List<Lesson1Test2> listItem = new List<Lesson1Test2>() { new Lesson1Test2(), new Lesson1Test2() };

    // 不支持字典
    // public Dictionary<int, string> testDic = new Dictionary<int, string>() { { 1, "123" } };
}

public class Lesson1Test2
{
    public int test1 = 1;
    public float test2 = 1.1f;
    public bool test3 = true;
}

Lesson1Test lt = new Lesson1Test();

2.进行序列化

XmlSerializer:用于序列化对象为 xml 的关键类

StreamWriter:用于存储文件

using:用于方便流对象释放和销毁

using System.Xml.Serialization;

// 第一步:确定存储路径
string path = Application.persistentDataPath + "/Lesson1Test.xml";

// 第二步:结合 using知识点 和 StreamWriter这个流对象 来写入文件
// 括号内的代码:写入一个文件流 如果有该文件 直接打开并修改 如果没有该文件 直接新建一个文件
// using 的新用法 括号当中包裹的声明的对象 会在 大括号语句块结束后 自动释放掉 
// 当语句块结束 会自动帮助我们调用 对象的 Dispose这个方法 让其进行销毁
// using一般都是配合 内存占用比较大 或者 有读写操作时  进行使用的 
using (StreamWriter stream = new StreamWriter(path)) {
    // 第三步:进行xml文件序列化
    XmlSerializer s = new XmlSerializer(typeof(Lesson1Test));
    
    // 这句代码的含义 就是通过序列化对象 对我们类对象进行翻译 将其翻译成我们的xml文件 写入到对应的文件中
    // 第一个参数:文件流对象
    // 第二个参数:想要备翻译 的对象
    // 注意:翻译机器的类型 一定要和传入的对象是一致的 不然会报错
    s.Serialize(stream, lt);
}

3.运行测试

运行后可以看到如下的文件内容(在 path 文件夹中查看)

可以发现,只能保存 public 类型的数据

<?xml version="1.0" encoding="utf-8"?>
<Lesson1Test xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <testPublic>10</testPublic>
  <testPUblicStr>123</testPUblicStr>
  <testClass>
    <test1>1</test1>
    <test2>1.1</test2>
    <test3>true</test3>
  </testClass>
  <arrayInt>
    <int>5</int>
    <int>6</int>
    <int>7</int>
  </arrayInt>
  <listInt>
    <int>1</int>
    <int>2</int>
    <int>3</int>
    <int>4</int>
  </listInt>
  <listItem>
    <Lesson1Test2>
      <test1>1</test1>
      <test2>1.1</test2>
      <test3>true</test3>
    </Lesson1Test2>
    <Lesson1Test2>
      <test1>1</test1>
      <test2>1.1</test2>
      <test3>true</test3>
    </Lesson1Test2>
  </listItem>
  <testPro>0</testPro>
</Lesson1Test>

4.自定义节点名或设置属性

public class Lesson1Test
{
    [XmlElement("testPublic123123")]  // 将该变量对应的结点名字改为 "testPublic123123"
    public    int          testPublic    = 10;
    private   int          testPrivate   = 11;
    protected int          testProtected = 12;
    internal  int          testInternal  = 13;
    public    string       testPUblicStr = "123";
    public    int          testPro { get; set; }
    public    Lesson1Test2 testClass = new Lesson1Test2();
    public    int[]        arrayInt  = new int[3] { 5, 6, 7 };

    [XmlArray("IntList")]    // 改变数组对应的结点名字
    [XmlArrayItem("Int32")]  // 改变数组成员对应的结点名字
    public List<int> listInt = new List<int>() { 1, 2, 3, 4 };

    public List<Lesson1Test2> listItem = new List<Lesson1Test2>() { new Lesson1Test2(), new Lesson1Test2() };

    // 不支持字典
    // public Dictionary<int, string> testDic = new Dictionary<int, string>() { { 1, "123" } };
}

public class Lesson1Test2
{
    [XmlAttribute("Test1")]    // 将该变量存储为XML属性,并改名为 "Test1"
    public int test1 = 1;
    
    [XmlAttribute]             // 将该变量存储为XML属性
    public float test2 = 1.1f;
    
    [XmlAttribute]          
    public bool test3 = true;
}
<?xml version="1.0" encoding="utf-8"?>
<Lesson1Test xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <testPublic>10</testPublic>
  <testPUblicStr>123</testPUblicStr>
  <testClass Test1="1" test2="1.1" test3="true" />
  <arrayInt>
    <int>5</int>
    <int>6</int>
    <int>7</int>
  </arrayInt>
  <IntList>
    <Int32>1</Int32>
    <Int32>2</Int32>
    <Int32>3</Int32>
    <Int32>4</Int32>
  </IntList>
  <listItem>
    <Lesson1Test2 Test1="1" test2="1.1" test3="true" />
    <Lesson1Test2 Test1="1" test2="1.1" test3="true" />
  </listItem>
  <testPro>0</testPro>
</Lesson1Test>

​5. 总结:

  • 序列化流程
    1. 有一个想要保存的类对象
    2. 使用 XmlSerializer 序列化该对象
    3. 通过 StreamWriter 配合 using 将数据存储 写入文件
  • 注意:
    1. 只能序列化公共成员
    2. 不支持字典序列化
    3. 可以通过特性修改节点信息或者设置属性信息
    4. Stream 相关要配合 using 使用

二、XML 反序列化

(一)判断文件是否存在

using System.IO;

string path = Application.persistentDataPath + "/Lesson1Test.xml";
if(File.Exists(path)) { ... }

(二)反序列化

​ 关键知识:

  1. using 和 StreamReader
  2. XmlSerializer 的 Deserialize 反序列化方法
using System.Xml.Serialization;

// 读取文件
using (StreamReader reader = new StreamReader(path))
{
    // 产生了一个 序列化反序列化的翻译机器
    XmlSerializer s = new XmlSerializer(typeof(Lesson1Test));
    Lesson1Test lt = s.Deserialize(reader) as Lesson1Test;
}

​ 运行后调试,可以发现 List 类型的内容被重复添加,原因是变量 lt 初始化后, List 中有默认值,而反序列化时,Deserialize 方法会往 List 中用 Add 方法添加值,而不是覆盖原有的值。

​ 总结:

  1. 判断文件是否存在 File.Exists()

  2. 文件流获取 StreamReader reader = new StreamReader(path)

  3. 根据文件流 XmlSerializer 通过 Deserialize 反序列化出对象

​ 注意:List 对象如果有默认值,反序列化时不会清空,会往后面添加

三、IXmlSerializable 接口

​ C# 的 XmlSerializer 提供了可拓展内容,可以让一些不能被序列化和反序列化的特殊类能被处理
​ 让特殊类继承 IXmlSerializable 接口,实现其中的方法即可

(一)回顾序列化与反序列化

using System.IO;
using System.Xml;
using System.Xml.Serialization;

public class TestLesson3 : IXmlSerializable
{
    public int test1;
    public string test2;
}

TestLesson3 t = new TestLesson3();
t.test2 = "123";
string path = Application.persistentDataPath + "/TestLesson3.xml";
// 序列化
using (StreamWriter writer = new StreamWriter(path))
{
    // 序列化"翻译机器"
    XmlSerializer s = new XmlSerializer(typeof(TestLesson3));
    // 在序列化时  如果对象中的引用成员 为空 那么xml里面是看不到该字段的
    s.Serialize(writer, t);
}
// 反序列化
using (StreamReader reader = new StreamReader(path))
{
    // 序列化"翻译机器"
    XmlSerializer s = new XmlSerializer(typeof(TestLesson3));
    TestLesson3 t2 = s.Deserialize(reader) as TestLesson3;
}
<?xml version="1.0" encoding="utf-8"?>
<TestLesson3 xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <test1>0</test1>
  <test2>123</test2>
</TestLesson3>

(二)继承 IXmlSerializable 接口

1.继承接口并实现接口函数

public class TestLesson3 : IXmlSerializable
{
    public int test1;
    public string test2;

    // 返回结构,返回 null 即可,不用过多了解
    public XmlSchema GetSchema()
    {
        return null;
    }

    // 反序列化时 会自动调用的方法
    public void ReadXml(XmlReader reader) { }

    // 序列化时 会自动调用的方法
    public void WriteXml(XmlWriter writer) { }
}

2.WriteXml

public void WriteXml(XmlWriter writer)
{
    // 在里面可以自定义序列化 的规则

    // 如果要自定义 序列化的规则 一定会用到 XmlWriter中的一些方法 来进行序列化
    // 1.写属性
    writer.WriteAttributeString("test1", this.test1.ToString());
    writer.WriteAttributeString("test2", this.test2);

    // 2.写节点
    writer.WriteElementString("test1", this.test1.ToString());
    writer.WriteElementString("test2", this.test2);

    // 3.写包裹节点
    XmlSerializer s = new XmlSerializer(typeof(int));
    writer.WriteStartElement("test1");  // 写 <test1>
    s.Serialize(writer, test1);         // 用序列化翻译机器写 test1 的内容
    writer.WriteEndElement();           // 写 </test1>

    XmlSerializer s2 = new XmlSerializer(typeof(string));
    writer.WriteStartElement("test2");  // 写 <test2>
    s.Serialize(writer, test2);         // 用序列化翻译机器写 test2 的内容
    writer.WriteEndElement();           // 写 </test2>
}

3.ReadXml

public void ReadXml(XmlReader reader)
{
    // 在里面可以自定义反序列化 的规则
    // 1.读属性
    this.test1 = int.Parse(reader["test1"]);
    this.test2 = reader["test2"];

    // 2.读节点
    // 方式一
    reader.Read();                         // 这时是读到的test1节点          <test1>
    reader.Read();                         // 这时是读到的test1节点包裹的内容  0
    this.test1 = int.Parse(reader.Value);  // 得到当前内容的值=
    reader.Read();                         // 这时读到的是尾部包裹节点        </test1>
    reader.Read();                         // 这时是读到的test2节点          <test2>
    reader.Read();                         // 这时是读到的test2节点包裹的内容  123
    this.test2 = reader.Value;

    // 方式二
    while (reader.Read()) 
    {
        if (reader.NodeType == XmlNodeType.Element) 
        {
            switch (reader.Name) 
            {
                case "test1":
                    reader.Read();
                    this.test1 = int.Parse(reader.Value);
                    break;
                case "test2":
                    reader.Read();
                    this.test2 = reader.Value;
                    break;
            }
        }
    }

    // 3.读包裹元素节点
    XmlSerializer s = new XmlSerializer(typeof(int));
    XmlSerializer s2 = new XmlSerializer(typeof(string));

    reader.Read();  // 跳过根节点
    
    reader.ReadStartElement("test1");     // 读 <test1>
    test1 = (int)s.Deserialize(reader);   // 用反序列化翻译机器读 test1 的内容
    reader.ReadEndElement();              // 读 </test1>

    reader.ReadStartElement("test2");            // 读 <test2>
    test2 = s2.Deserialize(reader).ToString();   // 用反序列化翻译机器读 test2 的内容
    reader.ReadEndElement();                     // 读 </test2>
}

四、Dictionary 支持序列化与反序列化

  1. 我们没办法修改 C# 自带的类

  2. 那我们可以重写一个类继承 Dictionary,然后让这个类继承序列化拓展接口 IXmlSerializable

  3. 实现里面的序列化和反序列化方法即可

public class SerizlizedDictionary<TKey, TValue> : Dictionary<TKey, TValue>, IXmlSerializable
{
    public XmlSchema GetSchema() {
        return null;
    }

    // 自定义字典的 反序列化 规则
    public void ReadXml(XmlReader reader) {
        XmlSerializer keySer   = new XmlSerializer(typeof(TKey));
        XmlSerializer valueSer = new XmlSerializer(typeof(TValue));

        // 要跳过根节点
        reader.Read();
        // 判断 当前不是元素节点 结束 就进行 反序列化
        while (reader.NodeType != XmlNodeType.EndElement) {
            // 反序列化键
            TKey key = (TKey)keySer.Deserialize(reader);
            // 反序列化值
            TValue value = (TValue)valueSer.Deserialize(reader);
            // 存储到字典中
            this.Add(key, value);
        }
    }

    // 自定义 字典的 序列化 规则
    public void WriteXml(XmlWriter writer) {
        XmlSerializer keySer   = new XmlSerializer(typeof(TKey));
        XmlSerializer valueSer = new XmlSerializer(typeof(TValue));

        foreach (KeyValuePair<TKey, TValue> kv in this) {
            // 键值对 的序列化
            keySer.Serialize(writer, kv.Key);
            valueSer.Serialize(writer, kv.Value);
        }
    }
}

(一)序列化测试

public class TestLesson4
{
    public int test1;

    public SerizlizerDictionary<int, string> dic;
}

public class Lesson4 : MonoBehaviour
{
    // Start is called before the first frame update
    void Start() {
        TestLesson4 tl4 = new TestLesson4();
        tl4.dic = new SerizlizerDictionary<int, string>();
        tl4.dic.Add(1, "123");
        tl4.dic.Add(2, "234");
        tl4.dic.Add(3, "345");
        
        string path = Application.persistentDataPath + "/TestLesson4.xml";
        using (StreamWriter writer = new StreamWriter(path)) {
            XmlSerializer s = new XmlSerializer(typeof(TestLesson4));
            s.Serialize(writer, tl4);
        }
    }
}
<?xml version="1.0" encoding="utf-8"?>
<TestLesson4 xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <test1>0</test1>
  <dic>
    <int>1</int>
    <string>123</string>
    <int>2</int>
    <string>234</string>
    <int>3</int>
    <string>345</string>
  </dic>
</TestLesson4>

(二)反序列化测试

void Start() {
    TestLesson4 tl4 = new TestLesson4();
    using (StreamReader reader = new StreamReader(path)) {
        XmlSerializer s = new XmlSerializer(typeof(TestLesson4)); 
        tl4 = s.Deserialize(reader) as TestLesson4;
    }
}

五、自定义 XML 数据管理类

using System;
using System.IO;
using System.Xml.Serialization;
using UnityEngine;

public class XmlDataMgr
{
    // 单例模式
    public static XmlDataMgr Instance { get; } = new XmlDataMgr();

    // 防止外部实例化该管理类
    private XmlDataMgr() { }

    /// <summary>
    /// 保存数据到xml文件中
    /// </summary>
    /// <param name="data">数据对象</param>
    /// <param name="fileName">文件名</param>
    public void SaveData(object data, string fileName) {
        // 1.得到存储路径
        string path = Application.persistentDataPath + "/" + fileName + ".xml";
        // 2.存储文件
        using (StreamWriter writer = new StreamWriter(path)) {
            // 3.序列化
            XmlSerializer s = new XmlSerializer(data.GetType());
            s.Serialize(writer, data);
        }
    }

    /// <summary>
    /// 从xml文件中读取内容 
    /// </summary>
    /// <param name="type">对象类型</param>
    /// <param name="fileName">文件名</param>
    /// <returns></returns>
    public object LoadData(Type type, string fileName) {
        // 1.首先要判断文件是否存在
        string path = Application.persistentDataPath + "/" + fileName + ".xml";
        if (!File.Exists(path)) {
            path = Application.streamingAssetsPath + "/" + fileName + ".xml";
            if (!File.Exists(path)) {
                // 如果根本不存在文件 两个路径都找过了
                // 那么直接new 一个对象 返回给外部 无非 里面都是默认值
                return Activator.CreateInstance(type);
            }
        }
        // 2.存在就读取
        using (StreamReader reader = new StreamReader(path)) {
            // 3.反序列化 取出数据
            XmlSerializer s = new XmlSerializer(type);
            return s.Deserialize(reader);
        }
    }
}
  if (!File.Exists(path)) {
            path = Application.streamingAssetsPath + "/" + fileName + ".xml";
            if (!File.Exists(path)) {
                // 如果根本不存在文件 两个路径都找过了
                // 那么直接new 一个对象 返回给外部 无非 里面都是默认值
                return Activator.CreateInstance(type);
            }
        }
        // 2.存在就读取
        using (StreamReader reader = new StreamReader(path)) {
            // 3.反序列化 取出数据
            XmlSerializer s = new XmlSerializer(type);
            return s.Deserialize(reader);
        }
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

iOS中的一些锁

多线程在日常开发中能起到性能优化的作用&#xff0c;但是一旦没用好就会造成线程不安全&#xff0c;本文就来讲讲如何保证线程安全 锁 线程安全 当一个线程访问数据的时候&#xff0c;其他的线程不能对其进行访问&#xff0c;直到该线程访问完毕。简单来讲就是在同一时刻&a…

智能垃圾桶

1.树莓派3B引脚图 2. 原理图 3.舵机线图 搜了这个这么多3b的资料&#xff0c;自己只是想解决如何下程序和运行程序的博客&#xff0c;网上搜集的资料全是讲如何通过SSH或者网线连接树莓派&#xff0c;通过直接连接屏幕的教程较少。 遇到问题&#xff1a;不论是舵机还是其他传…

Fragment的基本用法、Fragment和活动间的通信、Fragment的生命周期、动态加载布局的技巧

一、Fragment的简单用法 1、制作Fragment 1.1 新建一个布局文件left_fragment.xml <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"android:orientation"ve…

Ansible 自动化运维工具

目录 Ansible 简介Ansible 特性&#xff1a;Ansible 工作机制 Ansible 环境安装部署管理端安装 ansibleansible 目录结构配置主机清单配置密钥对验证ansible 命令行模块1&#xff0e;command 模块2&#xff0e;shell 模块3&#xff0e;cron 模块4&#xff0e;user 模块5&#x…

无GPS下的自动驾驶系统解决方案

摘要&#xff1a; 随着自动驾驶技术的发展&#xff0c;在未知环境中智能汽车的定位技术成为该领域研究的核心。目前定位技术主要的解决方案是基于全球定位系统&#xff08;GPS&#xff09;&#xff0c;但是在某些特殊的环境中如下车库&#xff0c;没有 GPS 信号如何解决定位问…

机器学习 day30(正则化参数λ对模型的影响)

λ对Jcv和Jtrain的影响 假设该模型为四阶多项式当λ很大时&#xff0c;在最小化J的过程中&#xff0c;w会很小且接近0&#xff0c;此时模型f(x)近似于一个常数&#xff0c;所以此时模型欠拟合&#xff0c;Jtrain和Jcv都很大当λ很小时&#xff0c;表示模型几乎没有正则化&…

如何在3ds max中创建可用于真人场景的巨型机器人:第 3 部分

推荐&#xff1a; NSDT场景编辑器助你快速搭建可二次开发的3D应用场景 1. 创建腿部装备 步骤 1 打开 3ds Max。 打开在本教程最后一部分中保存的文件。 打开 3ds Max 步骤 2 转到创建> 系统并单击骨骼。 创建>系统 步骤 3 为的 侧视口中的腿&#xff0c;如下图所示…

蓝桥杯单片机第八届国赛 真题+代码

iic.c /* # I2C代码片段说明1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。2. 参赛选手可以自行编写相关代码或以该代码为基础&#xff0c;根据所选单片机类型、运行速度和试题中对单片机时钟频率的要求&#xff0c;进行代码调试和修改。 */ #include <STC1…

static关键字和继承

1、static关键字 1.1案例题目 • 编程实现People类的封装&#xff0c;特征有&#xff1a;姓名、年龄、国籍&#xff0c;要求提供打印所有特征的方法。 • 编程实现PeopleTest类&#xff0c;main方法中使用有参方式构造两个对象并打印。 /*编程实现People类的封装*/ public cl…

Python基础教程:sklearn机器学习入门

1. sklearn基础介绍 sklearn&#xff08;全名为scikit-learn&#xff09;是一个建立在NumPy、SciPy和matplotlib等科学计算库的基础上&#xff0c;用于机器学习的Python开源库。它提供了丰富的工具和函数&#xff0c;用于处理各种机器学习任务&#xff0c;包括分类、回归、聚类…

【JavaEE初阶】Servlet (二) Servlet中常用的API

文章目录 HttpServlet核心方法 HttpServletRequest核心方法 HttpServletResponse核心方法 Servlet中常用的API有以下三个: HttpServletHttpServletRequestHttpServletResponse HttpServlet 我们写 Servlet 代码的时候, 首先第一步就是先创建类, 继承自 HttpServlet, 并重写其…

SpringBoot+Prometheus+Grafana实现系统可视化监控

场景 SpringBoot中集成Actuator实现监控系统运行状态&#xff1a; SpringBoot中集成Actuator实现监控系统运行状态_springboot actuator 获取系统运行时长_霸道流氓气质的博客-CSDN博客 基于以上Actuator实现系统监控&#xff0c;还可采用如下方案。 Prometheus Prometheu…

「2024」预备研究生mem-带绝对值的方程高次方程替代降次法

一、带绝对值的方程 二、高次方程替代降次法

用VMware给运行在VMware上的CentOS7生成一个以SSH方式连接VMware上的CentOS7的运行在Windows上的命令行窗口

2023年7月27日&#xff0c;周四早上 目录 一个发现生成方法如果上面的方法连接失败&#xff0c;就采取这个方法 一个发现 今天早上无意间发现VMware可以生成一个以SSH方式连接着CentOS7的Windows命令行窗口&#xff0c; 这样做可以带来一定的便利性 &#xff1a; 方便复制、…

Django模板语法和请求

1、在django关于模板文件加载顺序 创建的django项目下会有一个seeetings.py的文件 如果在seeetings.py 中加了 os.path.join(BASE_DIR,‘templates’)&#xff0c;如果是pycharm创建的django项目会加上&#xff0c;就会默认先去根目录找templates目录下的html文件&#xff0c…

时间复杂度函数图像

复杂度一览 f(n)阶函数y1O(1)常数函数ylogxO(logn)对数函数yxO(n)线性函数yxlogxO(nlogn)线性对数函数yx^2O(n^2)二次函数yx^3O(n^3)三次函数y2^xO(2^n)指数函数 对比图一览 对比结果在线预览 参考 时间复杂度比较及时间复杂度对应函数&#xff0c;函数图像

【机器学习】 奇异值分解 (SVD) 和主成分分析 (PCA)

一、说明 在机器学习 &#xff08;ML&#xff09; 中&#xff0c;一些最重要的线性代数概念是奇异值分解 &#xff08;SVD&#xff09; 和主成分分析 &#xff08;PCA&#xff09;。收集到所有原始数据后&#xff0c;我们如何发现结构&#xff1f;例如&#xff0c;通过过去 6 天…

VirtualEnv 20.24.0 发布

导读VirtualEnv 20.24.0 现已发布&#xff0c;VirtualEnv 用于在一台机器上创建多个独立的 Python 运行环境&#xff0c;可隔离项目之间的第三方包依赖&#xff0c;为部署应用提供方便&#xff0c;把开发环境的虚拟环境打包到生产环境即可&#xff0c;不需要在服务器上再折腾一…

郑州Sectigo DV通配符SSL证书

我们在浏览器访问网页时或许不会注意到网站是http还是https链接&#xff0c;但是一定能注意到浏览器给我们展示的“不安全”警告&#xff0c;警告访问者网站未加密&#xff0c;访问网站会有泄露隐私的危险。SSL证书能将网站链接由http转为https&#xff0c;对网站传输数据加密&…

【redis】通过配置文件简述redis的rdb和aof

redis的持久化方式有2种&#xff0c;rdb&#xff0c;即通过快照的方式将全量数据以二进制记录在磁盘中&#xff0c;aof&#xff0c;仅追加文件&#xff0c;将增量的写命令追加在aof文件中。在恢复的时候&#xff0c;rdb要更快&#xff0c;但是会丢失一部分数据。aof丢失数据极少…