简单数据结构的最轻序列化方法
Lightest serialization method for simple data structure
我有一个简单的数据结构,我想在不增加太多开销的情况下对其进行序列化。
就数据大小而言,您认为哪种方法最好?
- 自定义 serialization/deserialization 使用分隔符作为“#”或我 100% 的其他字符不存在于我的数据中
- XmlSerialization
- JSON
- 其他
我使用自定义序列化并以 # 作为分隔符,因为我 100% 确定我的数据中没有该字符。
数据结构示例:
string Title
int ChapterIndex
List<String> Paragraphs
我有上面object的列表
- 无优化(制表符和空格)
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>
- 优化(没有不必要的字符)
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
有
- ¤ 作为列表项分隔符
- § 作为项目分隔符内的属性
- # 作为段落内容分隔符
更新:
在我的例子中,我的字符串多于整数,因为它是一种 book/lyrics 应用程序,只需要标题 chapternumber/lyricId 和歌词的所有段落。
在我看来 JSON 是最简单的方法,而且不会产生任何开销。
在这里: http://json.org/example 你可以看到 JSON 和 XML 之间的区别。
JSON 解析器会自动为您完成所有工作。
我一直在我的项目中使用 google 的 proto-buf 序列化,它是迄今为止最轻量级的序列化之一。
决定起来很复杂。如果您的 类 主要由字符串组成,那么您的方法更好。唯一的 "more better" 方法是压缩生成的流(创建序列化数据后您仍然可以做的事情)。
如果你的数据主要是numeric/non-string,那么BinaryFormatter/protobuf是二进制序列化器,它们的输出应该比你的序列化器小,因为你使用5个字节来序列化10000
,而二进制序列化程序可能只使用 2-4 个字节。
Json 和 xml 序列化器肯定会产生更大的序列化数据,因为它们都是 "textual" (因此它们将数字 10000
序列化为 10000
) (和你的序列化程序一样)和 它们包含额外的标记,这些标记是非空的,根据定义不小于单个字符。
现在...编写自定义序列化程序或使用 protobuf 哪个更好?我会说我更相信由 Marc Gravell (protobuf) 编写并基于 google 创建的 "standard" 的序列化程序,而不是我编写的序列化程序 :-) 因为现在你正在序列化整数和字符串……但也许明天您需要序列化 DateTime
或 float
或其他复杂类型。比正确实现序列化所需的时间少 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
可能仍然更好,因为它是由专业人士编写的,并且没有作为序列化程序的限制。
在尝试了答案中提供的所有序列化类型后,我找到了问题的答案。
当并且仅当要求是这些时:
- 数据大小优先级
- 简单的数据结构
- 需要自定义序列化和反序列化
- 了解数据内容以正确选择分隔符
只有在这些条件下才能使用自定义序列化,如我的问题所示。
关于性能?
这完全取决于您如何编写 de/serialization 方法。
我有一个简单的数据结构,我想在不增加太多开销的情况下对其进行序列化。 就数据大小而言,您认为哪种方法最好?
- 自定义 serialization/deserialization 使用分隔符作为“#”或我 100% 的其他字符不存在于我的数据中
- XmlSerialization
- JSON
- 其他
我使用自定义序列化并以 # 作为分隔符,因为我 100% 确定我的数据中没有该字符。
数据结构示例:
string Title
int ChapterIndex
List<String> Paragraphs
我有上面object的列表
- 无优化(制表符和空格)
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>
- 优化(没有不必要的字符)
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
有
- ¤ 作为列表项分隔符
- § 作为项目分隔符内的属性
- # 作为段落内容分隔符
更新: 在我的例子中,我的字符串多于整数,因为它是一种 book/lyrics 应用程序,只需要标题 chapternumber/lyricId 和歌词的所有段落。
在我看来 JSON 是最简单的方法,而且不会产生任何开销。 在这里: http://json.org/example 你可以看到 JSON 和 XML 之间的区别。
JSON 解析器会自动为您完成所有工作。
我一直在我的项目中使用 google 的 proto-buf 序列化,它是迄今为止最轻量级的序列化之一。
决定起来很复杂。如果您的 类 主要由字符串组成,那么您的方法更好。唯一的 "more better" 方法是压缩生成的流(创建序列化数据后您仍然可以做的事情)。
如果你的数据主要是numeric/non-string,那么BinaryFormatter/protobuf是二进制序列化器,它们的输出应该比你的序列化器小,因为你使用5个字节来序列化10000
,而二进制序列化程序可能只使用 2-4 个字节。
Json 和 xml 序列化器肯定会产生更大的序列化数据,因为它们都是 "textual" (因此它们将数字 10000
序列化为 10000
) (和你的序列化程序一样)和 它们包含额外的标记,这些标记是非空的,根据定义不小于单个字符。
现在...编写自定义序列化程序或使用 protobuf 哪个更好?我会说我更相信由 Marc Gravell (protobuf) 编写并基于 google 创建的 "standard" 的序列化程序,而不是我编写的序列化程序 :-) 因为现在你正在序列化整数和字符串……但也许明天您需要序列化 DateTime
或 float
或其他复杂类型。比正确实现序列化所需的时间少 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
可能仍然更好,因为它是由专业人士编写的,并且没有作为序列化程序的限制。
在尝试了答案中提供的所有序列化类型后,我找到了问题的答案。
当并且仅当要求是这些时:
- 数据大小优先级
- 简单的数据结构
- 需要自定义序列化和反序列化
- 了解数据内容以正确选择分隔符
只有在这些条件下才能使用自定义序列化,如我的问题所示。
关于性能?
这完全取决于您如何编写 de/serialization 方法。