使用 Protobuf-net 将大数据文件流式传输为 IEnumerable

Posted

技术标签:

【中文标题】使用 Protobuf-net 将大数据文件流式传输为 IEnumerable【英文标题】:Use Protobuf-net to stream large data files as IEnumerable 【发布时间】:2011-08-26 12:38:56 【问题描述】:

我正在尝试使用 Protobuf-net 将数据保存并加载到磁盘但卡住了。

我有一个需要处理的资产组合,我希望能够尽快完成。我已经可以从 CSV 读取,但使用二进制文件会更快,所以我正在研究 Protobuf-Net。

我无法将所有资产都放入内​​存,因此我想将它们流式传输,而不是将它们全部加载到内存中。

所以我需要做的是将大量记录公开为 IEnumerable。 Protobuf-Net 有可能吗?我已经尝试了几件事,但无法让它运行。

序列化似乎有效,但我无法再次读回它们,我得到了 0 个资产。有人可以指出我正确的方向吗?查看了Serializer 类中的方法,但找不到任何涵盖这种情况的方法。 Protobuf-net 支持这个用例吗?顺便说一句,我正在使用 V2。

提前致谢,

格特-简

这是我尝试过的一些示例代码:

public partial class MainWindow : Window 

    // Generate x Assets
    IEnumerable<Asset> GenerateAssets(int Count) 
        var rnd = new Random();
        for (int i = 1; i < Count; i++) 
            yield return new Asset 
                ID = i,
                EAD = i * 12345,
                LGD = (float)rnd.NextDouble(),
                PD = (float)rnd.NextDouble()
            ;
        
    

    // write assets to file
    private void Write(string path, IEnumerable<Asset> assets)
        using (var file = File.Create(path)) 
            Serializer.Serialize<IEnumerable<Asset>>(file, assets);
        
    

    // read assets from file
    IEnumerable<Asset> Read(string path) 
        using (var file = File.OpenRead(path)) 
            return Serializer.DeserializeItems<Asset>(file, PrefixStyle.None, -1);
        
    

    // try it 
    private void Test() 
        Write("Data.bin", GenerateAssets(100)); // this creates a file with binary gibberish that I assume are the assets
        var x = Read("Data.bin");
        MessageBox.Show(x.Count().ToString()); // returns 0 instead of 100
    

    public MainWindow() 
        InitializeComponent();
    

    private void button2_Click(object sender, RoutedEventArgs e) 
        Test();
    


[ProtoContract]
class Asset 

    [ProtoMember(1)]
    public int ID  get; set; 

    [ProtoMember(2)]
    public double EAD  get; set; 

    [ProtoMember(3)]
    public float LGD  get; set; 

    [ProtoMember(4)]
    public float PD  get; set; 

【问题讨论】:

抱歉,我没办法了——还有几天的事了。很高兴你找到了答案。 不用担心没多久。非常感谢您(重新)编写整个内容! 【参考方案1】:

想通了。要反序列化使用 PrefixBase.Base128 至极显然 is the default。

现在它就像一个魅力!

GJ

        using (var file = File.Create("Data.bin")) 
            Serializer.Serialize<IEnumerable<Asset>>(file, Generate(10));
        

        using (var file = File.OpenRead("Data.bin")) 
            var ps = Serializer.DeserializeItems<Asset>(file, PrefixStyle.Base128, 1);
            int i = ps.Count(); // got them all back :-)
        

【讨论】:

以上是关于使用 Protobuf-net 将大数据文件流式传输为 IEnumerable的主要内容,如果未能解决你的问题,请参考以下文章

将大字符串流式传输到 JAXB

为啥我的代码中的 protobuf-net 反序列化器比流式读取 csv 慢得多

将大文件发送到 BigQuery

JDBC流式读取

JDBC流式读取

JDBC流式读取