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

本文关键字:IEnumerable 传输 文件 Protobuf-net 大型 数据 使用 | 更新日期: 2023-09-27 18:06:48

我试图使用Protobuf-net来保存和加载数据到磁盘,但被卡住了。

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

我不能把所有的资源都放到内存中,所以我想把它们流式传输,而不是全部加载到内存中。

所以我需要做的是公开一个大的记录集作为IEnumerable。这是可能的Protobuf-Net吗?我试了几样东西,但都没能让它运行起来。

序列化似乎有效,但我无法再次读取它们,我得到0资产。有人能给我指个正确的方向吗?查看Serializer类中的方法,但找不到任何涵盖这种情况的方法。这个用例是否被Protobuf-net支持?我用的是V2。

提前感谢,

Gert-Jan

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

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; }
}

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

明白了。要反序列化,使用PrefixBase。Base128显然是默认值。

现在它像一个魅力!

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 :-)
        }