【问题标题】:Lightest serialization method for simple data structure最简单的数据结构序列化方法
【发布时间】:2015-06-23 22:26:32
【问题描述】:

我有一个简单的数据结构,我想在不增加太多开销的情况下对其进行序列化。 就数据大小而言,您认为哪种方法最好?

  • 使用分隔符作为“#”或其他我 100% 的字符的自定义序列化/反序列化不存在于我的数据中
  • XmlSerialization
  • JSON
  • 其他

我正在使用带有 # 作为分隔符的自定义序列化,因为我 100% 确定我的数据中没有该字符。

数据结构示例:

string        Title       
int           ChapterIndex
List<String>  Paragraphs

我有上面的对象列表

  1. 没有优化(制表符和空格)

JSON:

[
 {
    "title": "some title 0",
    "chapterIndex": 0,
    "paragraphs": ["p1", "p2", "p3", "p4"]
 },
 {
    "title": "some title 1",
    "chapterIndex": 1,
    "paragraphs": ["p1chap1", "p2chap1", "p3chap1", "p4chap1"]
 }
]

XML:

<RootTag>
    <item title="some title 0" chapterIndex="0">
        <paragraph>p1</paragraph>
        <paragraph>p2</paragraph>
        <paragraph>p3</paragraph>
        <paragraph>p4</paragraph>
    </item>
    <item title="some title 1" chapterIndex="1">
        <paragraph>p1chap1</paragraph>
        <paragraph>p2chap1</paragraph>
        <paragraph>p3chap1</paragraph>
        <paragraph>p4chap1</paragraph>
    </item>
</RootTag>
  1. 优化(没有不必要的字符)

JSON:

[{"title":"some title 0","chapterIndex":0,"paragraphs":["p1","p2","p3","p4"]},{"title":"some title 1","chapterIndex":1,"paragraphs":["p1chap1","p2chap1","p3chap1","p4chap1"]}]

XML:

<RootTag><item title="some title 0" chapterIndex="0"><paragraph>p1</paragraph><paragraph>p2</paragraph><paragraph>p3</paragraph><paragraph>p4</paragraph></item><item title="some title 1" chapterIndex="1"><paragraph>p1chap1</paragraph><paragraph>p2chap1</paragraph><paragraph>p3chap1</paragraph><paragraph>p4chap1</paragraph></item></RootTag>

自定义:

some title 0##0##p1#p2#p3#p4###some title 1##1##p1chap1#p2chap1#p3chap1#p4chap1###and_so_on

自定义优化:

some title 0§0§p1#p2#p3#p4¤some title 1§1§p1chap1#p2chap1#p3chap1#p4chap1¤and_so_on

拥有

  • ¤ 作为列表项分隔符
  • § 作为项目分隔符内的属性
  • #作为段落内容分隔符

更新: 就我而言,我的字符串多于整数,因为它是一种书籍/歌词应用程序,只需要标题章节编号/歌词 ID 和歌词的所有段落。

【问题讨论】:

    标签: c# xml json serialization xml-serialization


    【解决方案1】:

    在尝试了答案中提供的所有序列化类型之后,我已经回答了我的问题。

    当且满足以下要求时:

    • 数据大小优先
    • 简单的数据结构
    • 需要自定义序列化和反序列化
    • 了解数据内容以正确选择分隔符

    只有在这些条件下才能使用自定义序列化,如我的问题所示。

    关于性能?
    这完全取决于您如何编写反序列化方法。

    【讨论】:

    • 我认为这是一个非常合理的结论。恭喜您真正思考您的问题。
    【解决方案2】:

    决定起来很复杂。如果您的类主要由字符串组成,那么您的方法是更好的方法。唯一“更好”的方法是压缩生成的流(在创建序列化数据后仍然可以这样做)。

    如果您的数据主要是数字/非字符串,那么BinaryFormatter/protobuf 是二进制序列化器,它们的输出应该小于您的序列化器,因为您使用 5 个字节序列化 10000,而二进制序列化程序可能只使用 2-4 个字节。

    Json 和 xml 序列化器肯定会产生更大的序列化数据,因为它们都是“文本”的(所以它们将数字 10000 序列化为 10000)(就像你的序列化器一样)它们包括额外的标记,这些标记是非空的,根据定义不小于单个字符。

    现在...是编写自定义序列化程序还是使用protobuf 更好?我会说我更相信 Marc Gravell (protobuf) 编写的序列化程序,它基于谷歌创建的“标准”,而不是我编写的序列化程序:-) 因为现在你正在序列化整数和字符串.. . 但也许明天您需要序列化DateTimefloat 或其他复杂类型。比您正确实现序列化所需的时间要少 100 个字节吗?是你自己来决定的。

    Protobuf 示例:

    [ProtoContract]
    public class MyObject
    {
        [ProtoMember(1)]
        public string title { get; set; }
        [ProtoMember(2)]
        public int chapterIndex { get; set; }
        [ProtoMember(3)]
        public List<String> paragraphs { get; set; }
    }
    
    var myo = new[] 
    { 
        new MyObject
        {
            title = "some title 0",
            chapterIndex = 0,
            paragraphs = new List<string> { "p1", "p2", "p3", "p4" }
        }, 
        new MyObject
        {
            title = "some title 1",
            chapterIndex = 1,
            paragraphs = new List<string> { "p1chap1", "p2chap1", "p3chap1", "p4chap1" }
        }, 
    };
    
    byte[] bytes;
    
    using (var ms = new MemoryStream())
    {
        Serializer.Serialize(ms, myo);
        bytes = ms.ToArray();
    }
    
    using (var ms = new MemoryStream(bytes))
    {
        MyObject[] myo2 = Serializer.Deserialize<MyObject[]>(ms);
    }
    

    byte[] 的长度为 86,因此仅比您的自定义格式化程序 (81) 长一点。但请注意,这是使用单个数字字段,并且您使用的是单个数字。关键是protobuf 可能仍然更好,因为它是由专业人士编写的,并且作为您的序列化程序没有任何限制。

    【讨论】:

    • @csharpwinphonexaml 好的...你是对的 :-) 所以我更新了答案。
    • 感谢您更新您的答案,考虑到我的数据主要是字符串,是否有一种混合方法可以将数字序列化为 char 以避免使用 4 字节作为 2 字节数字?您能否根据我的数据提供 protobuf 中的序列化结果示例?
    • @csharpwinphonexaml 完成第二部分。对于第一部分,我不会帮你浪费时间来节省一些字节
    【解决方案3】:

    在我看来,JSON 是最简单的方法,也不会产生任何开销。 在这里:http://json.org/example 你可以看到 JSON 和 XML 的区别。

    JSON 解析器会自动为您完成所有工作。

    【讨论】:

    • 我不确定是否没有开销,总是有开销/额外数据来分隔项目
    • 在我看来这不是开销。对我来说,开销就是 XML 的作用。编辑:但我认为你的方法更短,看起来还不错。
    • 你说得对,我误解了开销词,将其解释为额外/附件
    • 没问题。好吧,我想你回答了你自己的问题。你应该使用你的方法。或者您对此主题还有其他问题吗?
    • 我正在等待回答 proto-buf 的人提供一个示例,看看这是否比自定义示例更好/更轻
    【解决方案4】:

    我一直在我的项目中使用 google 的 proto-buf 序列化,它是迄今为止最轻的序列化之一。

    【讨论】:

      猜你喜欢
      • 2017-10-15
      • 1970-01-01
      • 2012-06-20
      • 2022-10-23
      • 1970-01-01
      • 1970-01-01
      • 2011-01-21
      • 2010-10-27
      • 2015-08-19
      相关资源
      最近更新 更多