【问题标题】:Serialization byte array vs XML file序列化字节数组与 XML 文件
【发布时间】:2010-10-08 21:42:16
【问题描述】:

我大量使用字节数组在网络上来回传输对象、原始数据。我通过让一个类型实现 ISerializable 来适应 java 的方法,它包含两个方法,作为接口的一部分,ReadObjectData 和 WriteObjectData。任何使用此接口的类都会将日期写入字节数组。类似的东西

  class SerializationType:ISerializable
    {
       void ReadObjectData (/*Type that manages the write/reads into the byte array*/){}
       void WriteObjectData(/*Type that manages the write/reads into the byte array*/){}  
    }

在所有对象的写入完成后,我发送一个网络数组。


这实际上是两个问题。是否是通过网络发送数据以获得最高效率(在速度、大小方面)的正确方法?

您是否会使用这种方法将对象写入文件,而不是通常使用 xml 序列化?

编辑#1

Joel Coehoorn 提到了 BinaryFormatter。我从来没有使用过这个类。除了我目前在 msdn 上看到的内容之外,您能否详细说明、提供好的示例、参考资料、建议、当前做法?

【问题讨论】:

    标签: c# .net networking file-io


    【解决方案1】:

    这应该没问题,但您所做的工作已经为您完成。查看System.Runtime.Serialization.Formatters.Binary.BinaryFormatter 类。

    您无需为每种特定类型实现自己的 Read/WriteOjbectData() 方法,您只需使用已经可以处理大多数任何对象的类即可。它基本上获取几乎所有 .Net 对象的内存表示的精确副本,并将其写入或从流中读取:

    BinaryFormatter bf = new BinaryFormatter();
    bf.Serialize(outputStream, objectToSerialize);
    
    objectToDeserialize = bf.Deserialize(inputStream) as DeserializedType;
    

    确保您通读了链接的文档:unicode 字符串可能存在问题,并且准确的内存表示并不总是合适的(例如,开放式套接字之类的东西)。

    【讨论】:

    • 如果需要二进制数组中的特定布局,这可能效果不佳。
    • 没错:它确实假设两端都是 .Net,或者任何非 .Net 参与者都会解析 .Net 格式。
    • BinaryFormatter 是特定于实现的、版本不兼容的,并且对于大型图来说不是特别快 - 但它当然对于 .net-to-.net 来说是完美的功能。就个人而言,我当然会选择 protobuf-net ;-p
    【解决方案2】:

    如果你追求简单、轻量和高效的二进制序列化,考虑protobuf-net;基于 google 的协议缓冲区格式,但从头开始实现典型的 .NET 使用。特别是,它既可以独立使用(通过 protobuf-net 的Serializer),也可以通过BinaryFormatter 通过实现ISerializable(并委托给Serializer)使用。

    除了高效之外,这种格式被设计为可扩展和可移植的(即与 java/php/C++“协议缓冲区”实现兼容),不像 BinaryFormatter 既是实现特定的又是版本不容忍的。这意味着您不必乱写任何序列化代码...

    【讨论】:

      【解决方案3】:

      当框架中已经有一个 ISerializable 接口时创建自己的 ISerializable 接口听起来有点像灾难的秘诀。至少给它一个不同的名字。

      在阅读时您会遇到一些问题 - 您将没有实例来调用该方法。你可能想把它变成一种“工厂”:

      public interface ISerializationFactory<T>
      {
          T ReadObjectData(Stream input);
          void WriteObjectData(Stream output);
      }
      

      至于 XML 与二进制...这完全取决于情况:会有多少数据,您是否需要向后和向前兼容性,.NET 中的 XML 序列化是否已经为您提供了足够的控制权等等。

      【讨论】:

      • ISerializationFactory 是什么时候引入的? ISerializable 是一个内部接口,所以我可以很容易地修改所有的序列化类型......我会记下它。谢谢
      【解决方案4】:

      是的,这将比发送 XML 更快,因为您将通过网络发送更少的数据。即使您压缩了 XML(这将大大减小其大小),您仍然会有压缩和解压缩的开销。所以我想说的是,在您目前正在做的事情和 XML 序列化之间,您目前使用的是最有效的解决方案。

      但是,我很好奇使用 XML 而不是编组对象会对性能造成多大影响。我鼓励您研究 XML 序列化的原因是因为您将以人类可读的与应用程序无关的格式存储数据。如果您能够以一种不会在您的应用程序中导致性能损失的方式将数据序列化为 XML,我建议您研究一下。

      【讨论】:

      • 好主意。我想对于存储文件,xml 文件是个好主意。至于电汇,具体到我的情况,我不能使用 xml,因为接收数据的另一端是 C++ 服务器,它只能以一种方式读取和写入数据,并且只有一种方式 - 到/从字节数组。谢谢
      【解决方案5】:

      关于写入文件,如果您希望能够读取序列化或可能更改它,通常您希望将对象序列化为 XML。如果您不希望序列化是人类可读的,那么您不妨重用您的二进制序列化。

      如果您确实希望它是人类可读的,那么 XML 是值得考虑的,但这取决于您需要序列化的数据类型。 XML 本质上是递归的,因此非常适合序列化同样的递归数据。它不太适合其他类型的数据。

      换句话说,选择适合您需求的持久序列化。这里没有万能的解决方案。

      对于网络,通常您希望将大小保持在最低限度,因此 XML 由于其冗长而通常不是一个好的选择。

      【讨论】:

        【解决方案6】:

        序列化(在 Java 中)看似简单。只要你做简单的事情(比如永远不要改变课程),这很容易——但它也有很多“有趣”的事情。

        请参阅Effective Java(特别是第 10 章)来详细讨论 Java 序列化。

        对于 C#,不确定,但核心问题可能是相同的。

        这里有一个关于 C# 序列化的示例:http://www.codeproject.com/KB/cs/objserial.aspx

        【讨论】:

        • Effective Java 是一本很棒的书——我从头到尾都阅读了两个版本!
        【解决方案7】:

        XStream 库提供了一种非常好的处理序列化的方法,包括支持 XML、JSON 和支持自定义转换器。具体来说,自定义转换器的使用使我们能够减少 XML 的冗长并严格序列化所需的内容。

        XStream 不需要将所有内容都声明为可序列化,这在使用第三方库并需要从该库中序列化未声明为可序列化的类的实例时非常重要。


        答案已经被接受,但为了讨论的完整性,这里提供了一个链接,可以很好地比较不同的序列化方法/库:

        http://code.google.com/p/thrift-protobuf-compare/wiki/Benchmarking

        kryo 库看起来非常适合 Java 序列化。与 XStream 类似的是支持自定义转换器。

        【讨论】:

        • 看起来不错 [供个人使用]。我不确定是否要将其包含在商业代码中,直到至少我完全理解许可指南。它仅有助于文件序列化。我也需要网络的东西。谢谢
        • 我们专门将它用于网络通信(作为 REST 服务和客户端之间通信的一种方式)。两分钟的教程 [xstream.codehaus.org/tutorial.html] 表明可以简单地编写 String xml = xstream.toXML(joe);然后用 xml 做任何需要的事情。
        猜你喜欢
        • 2013-05-01
        • 1970-01-01
        • 2016-03-03
        • 2011-09-29
        • 1970-01-01
        • 2011-08-07
        • 1970-01-01
        • 2012-03-09
        相关资源
        最近更新 更多