我已经构建了标准的地址簿教程,它附带了protobuf-csharp-port,我的代码如下所示:
class Program
{
static void Main(string[] args)
{
CreateData();
ShowData();
}
private static void CreateData()
{
AddressBook.Builder abb = new AddressBook.Builder();
for (int i = 0; i < 2000000; i++)
{
Person.Builder pb = new Person.Builder();
pb.Id = i;
pb.Email = "mytest@thisisatest.com";
pb.Name = "John" + i;
abb.AddPerson(pb.Build());
}
var ab = abb.Build();
var fs = File.Create("c:\\testaddressbook.bin");
ab.WriteTo(fs);
fs.Close();
fs.Dispose();
}
private static void ShowData()
{
var fs = File.Open("c:\\testaddressbook.bin", FileMode.Open, FileAccess.Read, FileShare.Read);
CodedInputStream cis = CodedInputStream.CreateInstance(fs);
cis.SetSizeLimit(Int32.MaxValue);
AddressBook ab = AddressBook.ParseFrom(cis);
Console.WriteLine("Person count: {0}", ab.PersonCount);
for (int i = 0; i < ab.PersonCount; i++)
Console.WriteLine("Name: " + ab.GetPerson(i).Name);
Console.WriteLine("Person count: {0}", ab.PersonCount);
fs.Close();
}
}在写入数据时,2m条记录占用300MB的RAM。在读取时,它占用大约415MB的RAM。
在XML世界中,我会使用一个轴函数来流式传输元素。是否可以流式传输地址簿模型对象中的记录?或者,也许有另一种方法可以实现这一点,以便更有效地使用内存?
谢谢
发布于 2011-03-19 02:55:52
是的,你可以流读和写。
有一个受官方Java API支持的版本,在我的C# API中也有一个使用WriteDelimitedTo/ParseDelimitedFrom的版本。
或者,您也可以使用MessageStreamWriter和MessageStreamIterator,这是我在分隔API出现之前引入到我的API中的。
发布于 2011-03-19 02:36:44
我不能评论这个实现,但在protobuf-net流媒体中是完全可能的。如果您想要流式传输的所有对象都是根对象的第一级子对象,那么您可以简单地迭代外部序列;如果它们都是同一类型,则使用Serializer.DeserializeItems<T>;如果涉及不同类型的对象,则使用Serializer.NonGeneric.TryDeaerializeWithLengthPrefix。
如果您希望作为流处理的项位于树的中间,则可以提供另一种接收模型;只需在伪集合上实现IEnumerable和Add(),它就可以通过您想要的任何应用程序接口(基于事件,例如类似于SAX )推送数据。
我还应该注意到,您可以用完全相同的方式序列化流数据。在任何时候都不需要有一个完整的对象模型。
如果你想要一个更完整的例子,请让我知道。
https://stackoverflow.com/questions/5356236
复制相似问题