当前位置: 主页 > 面试题 > 正文

c++序列化,和反序列化?

2025-04-26 16:47人气:0 编辑:招聘街

一、c++序列化,和反序列化?

序列化:将对象变成字节流的形式传出去。

反序列化:从字节流恢复成原来的对象。

二、什么是序列化,为什么要序列化?

序列化可以将内存中的类写入文件或数据库中。比如将某个类序列化后存为文件,下次读取时只需将文件中的数据反序列化就可以将原先的类还原到内存中。也可以将类序列化为流数据进行传输。总的来说就是将一个已经实例化的类转成文件存储,下次需要实例化的时候只要反序列化即可将类实例化到内存中并保留序列化时类中的所有变量和状态。

例如:hibernate中实体类的钝化就是将类序列化后存入磁盘并释放内存空间。

三、什么叫序列化?

序列化 是将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。

序列化使其他代码可以查看或修改,那些不序列化便无法访问的对象实例数据。

四、图片JS序列化怎么实现?

谢邀。

对这个真不了解,有点惭愧。

幸好以前看过相关博客,列表如下,可以参考一下思路。

具体如下:

五、rpc序列化协议?

常用的RPC序列化协议包括:Thrift、Protobuf、Avro、Kryo、MsgPack 、Hessian、Jackson。

· 传输协议。常用的传输协包括:HTTP、Socket、TCP、UDP等。

· 连接。连接包括:长连接、短连接。

· IO模型。常用的网络IO模型:同步阻塞IO(Blocking IO)、同步非阻塞IO(Non-blocking IO)、IO多路复用(IO Multiplexing)、异步IO(Asynchronous IO)。

六、redis序列化原理?

Redis,序列化,统一服务框架 ,并成功的实现一笔数,指定协议格式并完成框架配合,总而言之,序列号的原理。

这是一个非常细节的问题,要是让你来把“对象”转化为字节流,你会怎么做?很容易想到的一个方法是xml(或者json)。

从而可以达到实现最终目的。

如果没有统一的服务框架,各个团队的服务提供方就需要各自实现一套序列化、反序列化、网络框架、连接池、收发线程、超时处理、状态机等“业务之外”的重复技术劳动,造成整体的低效。

七、redis序列化作用?

redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。

redis是一个key-value存储系统。

和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set--有序集合)和hash(哈希类型)。

这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。

与memcached一样,为了保证效率,数据都是缓存在内存中。

区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

redis是一个高性能的key-value数据库。

redis的出现,很大程度补偿了memcached这类key/value存储的不足,在部分场合可以对关系数据库起到很好的补充作用。

redis提供了Java,C/C++,C#,PHP,JavaScript,Perl,Object-C,Python,Ruby,Erlang等客户端,使用很方便。

八、redis 不序列化 配置?

// 3.创建 序列化类 GenericToStringSerializer genericToStringSerializer = new GenericToStringSerializer(Object.class); // 6.序列化类,对象映射设置 // 7.设置 value 的转化格式和 key 的转化格式 redisTemplate.setValueSerializer(genericToStringSerializer); redisTemplate.setKeySerializer(new StringRedisSerializer());

九、net的序列化特性?

序列化通俗地讲就是将一个对象转换成一个字节流的过程,这样就可以轻松保存在磁盘文件或数据库中。反序列化是序列化的逆过程,就是将一个字节流转换回原来的对象的过程。

然而为什么需要序列化和反序列化这样的机制呢?这个问题也就涉及到序列化和反序列化的用途了,

对于序列化的主要用途有:

1)、将应用程序的状态保存在一个磁盘文件或数据库中,并在应用程序下次运行时恢复状态。例如, Asp.net 中利用序列化和反2)、序列化来保存和恢复会话状态。3)、一组对象可以轻松复制到Windows 窗体的剪贴板中,再粘贴回同一个或者另一个应用程序。将对象按值从一个应用程序域中发送到另一个程序域并且如果把对象序列化成内存中的字节流,就可以利用一些其他的技术来处理数据,例如,对数据进行加密和压缩等。

序列化和反序列化的简单使用:

using System;

using System.IO;

using System.Runtime.Serialization.Formatters.Binary;

 

namespace Serializable

{

 [Serializable]

 public class Person

 {

  public string personName;

 

  [NonSerialized]

  public string personHeight;

 

  private int personAge;

  public int PersonAge

  {

   get { return personAge; }

   set { personAge = value; }

  }

 

  public void Write()

  {

   Console.WriteLine("Person Name: "+personName);

   Console.WriteLine("Person Height: " +personHeight);

   Console.WriteLine("Person Age: "+ personAge);

  }

   

 }

 class Program

 {

  static void Main(string[] args)

  {

   Person person = new Person();

   person.personName = "Jerry";

   person.personHeight = "175CM";

   person.PersonAge = 22;

   Stream stream = Serialize(person);

 

   //为了演示,都重置

   stream.Position = 0;

   person = null;

 

   person = Deserialize(stream);

   person.Write();

   Console.Read();

    

  }

  private static MemoryStream Serialize(Person person)

  {

   MemoryStream stream = new MemoryStream();

 

   // 构造二进制序列化格式器

   BinaryFormatter binaryFormatter = new BinaryFormatter();

   // 告诉序列化器将对象序列化到一个流中

   binaryFormatter.Serialize(stream, person);

 

   return stream;

 

  }

 

  private static Person Deserialize(Stream stream)

  {

   BinaryFormatter binaryFormatter = new BinaryFormatter();

   return (Person)binaryFormatter.Deserialize(stream);

  }

   

 }

}

主要是调用System.Runtime.Serialization.Formatters.Binary命名空间下的BinnaryFormatter类来进行序列化和反序列化,

从中可以看出除了标记NonSerialized的其他成员都能序列化,注意这个属性只能应用于一个类型中的字段,而且会被派生类型继承。

SOAP 和XML 的序列化和反序列化和上面类似,只需要改下格式化器就可以了, 这里我就不列出来了。

三、控制序列化和反序列化  有两种方式来实现控制序列化和反序列化:

通过OnSerializing, OnSerialized,OnDeserializing, OnDeserialized,NonSerialized和OptionalField等属性实现System.Runtime.Serialization.ISerializable接口第一种方式实现控制序列化和反序列化代码:

using System;

using System.IO;

using System.Runtime.Serialization;

using System.Runtime.Serialization.Formatters.Binary;

 

namespace ControlSerialization

{

  [Serializable]

  public class Circle

  {

    private double radius; //半径

    [NonSerialized]

    public double area; //面积

 

    public Circle(double inputradiu)

    {

      radius = inputradiu;

      area = Math.PI * radius * radius;

    }

 

    [OnDeserialized]

    private void OnDeserialized(StreamingContext context)

    {

      area = Math.PI * radius * radius;

    }

 

    public void Write()

    {

      Console.WriteLine("Radius is: " + radius);

      Console.WriteLine("Area is: " + area);

    }

  }

  class Program

  {

     

    static void Main(string[] args)

    {

      Circle c = new Circle(10);

      MemoryStream stream =new MemoryStream();

      BinaryFormatter formatter = new BinaryFormatter();

      // 将对象序列化到内存流中,这里可以使用System.IO.Stream抽象类中派生的任何类型的一个对象, 这里我使用了 MemoryStream类型。

      formatter.Serialize(stream,c);

      stream.Position = 0;

      c = null;

      c = (Circle)formatter.Deserialize(stream);

      c.Write();

      Console.Read();

 

    }

  }

}

注意:如果注释掉 OnDeserialized属性的话,area字段的值就是0了,因为area字段没有被序列化到流中。 

在上面需要序列化的对象中,格式化器只会序列化对象的radius字段的值。area字段中的值不会序列化,因为该字段已经应用了NonSerializedAttribute属性,然后我们用Circle c=new Circle(10)这样代码构建一个Circle对象时,在内部,area会设置一个约为314.159这样的值,这个对象序列化时,只有radius的字段的值(10)写入流中, 但当反序列化成一个Circle对象时,它的area字段的值会初始化为0,而不是约314.159的一个值。为了解决这样的问题,所以自定义一个方法应用OnDeserializedAttribute属性。此时的执行过程为:每次反序列化类型的一个实例,格式化器都会检查类型中是否定义了 一个应用了该attribute的方法,如果是,就调用该方法,调用该方法时,所有可序列化的字段都会被正确设置。除了OnDeserializedAttribute这个定制attribute,system.Runtime.Serialization命名空间还定义了OnSerializingAttribute,OnSerializedAttribute和OnDeserializingAttribute这些定制属性。

实现ISerializable接口方式控制序列化和反序列化代码: 

using System;

using System.IO;

using System.Runtime.Serialization;

using System.Runtime.Serialization.Formatters.Binary;

using System.Security.Permissions;

 

namespace ControlSerilization2

{

  [Serializable]

  public class MyObject : ISerializable

  {

    public int n1;

    public intn2;

 

    [NonSerialized]

    public String str;

 

    public MyObject()

    {

    }

 

    protected MyObject(SerializationInfo info, StreamingContext context)

    {

      n1 = info.GetInt32("i");

      n2 = info.GetInt32("j");

      str = info.GetString("k");

    }

 

    [SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)]

    public virtual void GetObjectData(SerializationInfo info, StreamingContext context)

    {

      info.AddValue("i", n1);

      info.AddValue("j", n2);

      info.AddValue("k", str);

    }

 

    public void Write()

    {

      Console.WriteLine("n1 is: " + n1);

      Console.WriteLine("n2 is: " + n2);

      Console.WriteLine("str is: " + str);

    }

  }

 

  class Program

  {

    static void Main(string[] args)

    {

      MyObject obj = new MyObject();

      obj.n1 = 2;

      obj.n2 = 3;

      obj.str = "Jeffy";

      MemoryStream stream = new MemoryStream();

      BinaryFormatter formatter = new BinaryFormatter();

      // 将对象序列化到内存流中,这里可以使用System.IO.Stream抽象类中派生的任何类型的一个对象, 这里我使用了 MemoryStream类型。

      formatter.Serialize(stream, obj);

      stream.Position = 0;

      obj = null;

      obj = (MyObject)formatter.Deserialize(stream);

      obj.Write();

      Console.Read();

    }

  }

}

此时的执行过程为:当格式化器序列化对象时,会检查每个对象,如果发现一个对象的类型实现了ISerializable接口,格式化器会忽视所有定制属性,改为构造一个新的System.Runtime.Serialization.SerializationInfo对象,这个对象包含了要实际为对象序列化的值的集合。构造好并初始化好SerializationInfo对象后,格式化器调用类型的GetObjectData方法,并向它传递对SerializationInfo对象的引用,GetObjectData方法负责决定需要哪些信息来序列化对象,并将这些信息添加到SerializationInfo对象中,通过调用AddValue方法来添加需要的每个数据,添加好所有必要的序列化信息后,会返回至格式化器,然后格式化器获取已经添加到SerializationInfo对象中的所有值,并将它们都序列化到流中,当反序列化时,格式化器从流中提取一个对象时,会为新对象分配内存,最初,这个对象的所有字段都设为0或null,然后,格式化器检查类型是否实现了ISerializable接口,如果存在这个接口, 格式化器就尝试调用一个特殊构造器,它的参数和GetObjectData方法的完全一致。

四、格式化器如何序列化和反序列化从上面的分析中可以看出,进行序列化和反序列化主要是格式化器在工作的,然而下面就是要讲讲格式化器是如何序列化一个应用了 SerializableAttribute 属性的对象。

1、格式化器调用FormatterServices的GetSerializableMembers方法:public static MemberInfo[] GetSerializableMembers(Type type,StreamingContext context);这个方法利用发射获取类型的public和private实现字段(标记了NonSerializedAttributee属性的字段除外)。方法返回由MemberInfo对象构成的一个数组,其中每个元素对应于一个可序列化的实例字段。2、对象被序列化,System.Reflection.MemberInfo对象数组传给FormatterServices的静态方法GetObjectData: public static object[] GetObjectData(Object obj,MemberInfo[] members);  这个方法返回一个Object数组,其中每个元素都标识了被序列化的那个对象中的一个字段的值。3、格式化器将程序集标识和类型的完整名称写入流中。4、格式化器然后遍历两个数组中的元素,将每个成员的名称和值写入流中。接下来是解释格式化器如何自动反序列化一个应用了 SerializableAttribute属性的对象。

1、格式化器从流中读取程序集标识和完整类型名称。2、格式化器调用FormatterServices的静态方法GetUninitializedObject: public static Object GetUninitializedObject(Type ttype);这个方法为一个新对象分配内存,但不为对象调用构造器。然而,对象的所有字段都被初始化为0或null.3格式化器现在构造并初始化一个MemberInfo数组,调用FormatterServices的GetSerializableMembers方法,这个方法返回序列化好、现在需要反序列化的一组字段。4、格式化器根据流中包含的数据创建并初始化一个Object数组。5、将对新分配的对象、MemberInfo数组以及并行Object数组的引用传给FormatterServices的静态方法PopulateObjectMembers:          public static Object PopulateObjectMembers(Object obj,MemberInfo[] members,Object[] data);这个方法遍历数组,将每个字段初始化成对应的值。

十、怎么破解序列化文件?

1).创建FileOutputStream(创建存取文件的FileOutputStream对象,如果文件不存在,它会自动被创建出来)

FileOutputStream fileStream=new FileOutputStream("MyGame.ser");

(2).创建ObjectOutputStream(它能让你写入对象,但无法直接地连接文件,所以需要参数的指引)

ObjectOutputStream os=new ObjectOutputStream(fileStream);

(3).写入对象(将变量所引用的对象序列化并写入MyGame.ser这个文件)

os.writeObject(characterOne);

os.writeObject(characterTwo);

os.writeObject(characterThree);

(4).关闭ObjectOutputStream(关闭所关联的输出串流)

os.close();

即:Object 写入 ObjectOutputStream 连接到 FileOutputStream 到文件

3.解序列化的步骤:还原对象

(1).创建FileInputStream(如果文件不存在就会抛出异常)

FileInputStream fileStream=new FileInputStream("MyGame.ser");

(2).创建ObjectInputStream(它知道如何读取对象,但是要链接的stream提供文件存取)

ObjectInputStream os=new ObjectInputStream(fileStream);

(3).读取对象(每次调用readObject方法都会从stream中读出下一个对象,读取顺序与写入顺序相同,次数超过会抛出异常)

Object one=os.readObject();

Object two=os.readObject();

Object three=os.readObject();

(4).转换对象类型(返回值是Object类型,因此必须转换类型)

GameCharacter elf=(GameCharacter)one;

GameCharacter troll=(GameCharacter)two;

GameCharacter magician=(GameCharacter)three;

(5).关闭ObjectInputStream(FileInputStream会自动跟着关掉)

os.close();

即:文件 被读取 FileInputStream 被连接 ObjectInputSteam 恢复成对象

显示全部

收起

相关文章
热门频道
  • 招聘信息
  • 待遇资讯
  • 工资资讯
  • 笔试题
  • 面试题

访问电脑版 | 返回首页 | 招聘街