Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/297.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Protobuf net v2和大型词典_C#_.net 4.0_Protobuf Net - Fatal编程技术网

C# Protobuf net v2和大型词典

C# Protobuf net v2和大型词典,c#,.net-4.0,protobuf-net,C#,.net 4.0,Protobuf Net,我有一个奇怪的情况发生,我不太明白 我有一个“dataset”类,它保存关于监测浮标的各种元数据,包括“传感器”列表 每个当前“传感器状态” 每个“sensorstate”都有一些元数据(时间戳、更改原因等),但最重要的是,它有一个字典 这些传感器通常有超过50k个数据点(相当于15分钟的数据读取时间),因此我想找到比默认的.NETBinaryFormatter更快的序列化方法,并设置一个可以非常快地序列化的设置 不幸的是,当我的值字典抛出一个异常时,反序列化出现了我的问题,因为已经有一个添加了

我有一个奇怪的情况发生,我不太明白

我有一个“dataset”类,它保存关于监测浮标的各种元数据,包括“传感器”列表

每个当前“传感器状态”

每个“sensorstate”都有一些元数据(时间戳、更改原因等),但最重要的是,它有一个
字典

这些传感器通常有超过50k个数据点(相当于15分钟的数据读取时间),因此我想找到比默认的.NET
BinaryFormatter
更快的序列化方法,并设置一个可以非常快地序列化的设置

不幸的是,当我的值字典抛出一个异常时,反序列化出现了我的问题,因为已经有一个添加了相同键的项,我唯一能让它反序列化的方法是启用“OverwriteList”,但我有点不确定为什么在序列化时没有任何重复键(这是一个字典),那么,为什么在反序列化时会有重复的键呢?这也带来了数据完整性问题

如果您能帮助解释这一点,我们将不胜感激

(另一方面,当给出ProtoMember属性ID时,它们是否需要对类或整个项目唯一?我正在寻找无损压缩建议,以便与protobuf net结合使用,因为文件越来越大)

编辑:

我刚刚在GitHub上发布了我的源代码,下面是有问题的类

(注意:为了使其能用于其他开发,它当前的OverwriteList=true)

这里有一个例子


我已经尝试使用SkipContractor标志,但即使将其设置为true,也会出现异常,除非OverwriteList对于值字典也是true。

如果
OverwriteList
修复了它,那么它向我建议字典默认情况下包含一些数据,可能是通过构造函数或类似方法。如果它确实来自构造函数,您可以使用
[ProtoContract(SkipConstructor=true)]
禁用它

如果我误解了上述内容,如果可能的话,可以用一个可复制的例子来说明

关于ID,它们只需要在每种类型中都是唯一的,并且建议保持它们的小型化(由于标记的“可变”编码,小型键比大型键“便宜”)

如果你真的想最小化数据的大小,我建议你也看看数据的内容。例如,你说这是15分钟的阅读。。。嗯,我猜偶尔会有间隙,但你能做些什么,例如:

Block (class)
    Start Time (DateTime)
    Values (float[])
对于每一个连续的15分钟值串,都有一个
(这里的假设是,每个值都是最后一个值之后的15,否则会启动一个新块)。因此,您正在存储多个
实例来代替单个字典。这有以下优点:

  • 要存储的
    DateTime
    值少得多
  • 您可以在浮动上使用“打包”编码,这意味着不需要添加所有中间标记;您可以通过将数组/列表标记为(
    [ProtoMember({key},IsPacked=true)]
    )来实现这一点,注意它只适用于少数基本数据类型(而不是子对象)
这两项调整结合起来可以产生显著的节约

如果数据有很多字符串,可以尝试GZIP/DEFLATE。当然,您可以尝试这两种方法,但是如果没有大量的字符串数据,我会小心地避免从压缩中获得太多额外的数据


作为基于提供的(CSV)数据文件的更新,在处理字典时没有固有的问题-如图所示:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using ProtoBuf;
class Program
{
    static void Main()
    {
        var data = new Data
        {
            Points =
            {
                {new DateTime(2009,09,1,0,0,0), 11.04F},
                {new DateTime(2009,09,1,0,15,0), 11.04F},
                {new DateTime(2009,09,1,0,30,0), 11.01F},
                {new DateTime(2009,09,1,0,45,0), 11.01F},
                {new DateTime(2009,09,1,1,0,0), 11F},
                {new DateTime(2009,09,1,1,15,0), 10.98F},
                {new DateTime(2009,09,1,1,30,0), 10.98F},
                {new DateTime(2009,09,1,1,45,0), 10.92F},
                {new DateTime(2009,09,1,2,00,0), 10.09F},
            }
        };

        var ms = new MemoryStream();
        Serializer.Serialize(ms, data);
        ms.Position = 0;
        var clone =Serializer.Deserialize<Data>(ms);
        Console.WriteLine("{0} points:", clone.Points.Count);
        foreach(var pair in clone.Points.OrderBy(x => x.Key))
        {
            float orig;
            data.Points.TryGetValue(pair.Key, out orig);
            Console.WriteLine("{0}: {1}", pair.Key, pair.Value == orig ? "correct" : "FAIL");
        }
    }
}
[ProtoContract]
class Data
{
    private readonly Dictionary<DateTime, float> points = new Dictionary<DateTime, float>();
    [ProtoMember(1)]
    public Dictionary<DateTime, float> Points { get { return points; } } 
}
使用系统;
使用System.Collections.Generic;
使用System.IO;
使用System.Linq;
使用ProtoBuf;
班级计划
{
静态void Main()
{
var数据=新数据
{
要点=
{
{新日期时间(2009,09,1,0,0,0),11.04F},
{新日期时间(2009,09,1,0,15,0),11.04F},
{新日期时间(2009,09,1,0,30,0),11.01F},
{新日期时间(2009,09,1,0,45,0),11.01F},
{新日期时间(2009,09,1,1,0,0),11F},
{新日期时间(2009,09,1,1,15,0),10.98F},
{新日期时间(2009,09,1,1,30,0),10.98F},
{新日期时间(2009,09,1,1,45,0),10.92F},
{新日期时间(2009,09,1,2,00,0),10.09F},
}
};
var ms=新内存流();
序列化器。序列化(ms、数据);
ms.Position=0;
var clone=序列化程序。反序列化(ms);
WriteLine(“{0}点:”,clone.points.Count);
foreach(clone.Points.OrderBy(x=>x.Key)中的变量对)
{
浮动原点;
data.Points.TryGetValue(pair.Key,out-orig);
Console.WriteLine(“{0}:{1}”,pair.Key,pair.Value==orig?”正确:“FAIL”);
}
}
}
[原始合同]
类数据
{
私有只读字典点=新字典();
[原成员(1)]
公共字典点{get{return Points;}}
}

这是我道歉的地方,因为我曾经暗示它与我自己没有做过的代码有关。而当我在这里为protobuf和Marc Gravell背后的protobuf net团队提供疯狂道具时,它真的很快

发生的事情是在类中,我有一些逻辑,从不让两个属性为空

[ProtoMember(12)]
public SensorState CurrentState
{
    get { return (_currentState == null) ? RawData : _currentState; }
    set { _currentState = value; }
}


我已经设置了[ProtoContract(SkipConstructor=true)],但问题仍然存在,我已经更新了我的帖子,链接到源代码并提供了原始数据文件。我的问题完全是我自己的,很抱歉,甚至暗示了其他问题:)嗨;我对SensorState进行了简要的介绍,但它并不是处于“最小”状态,我实际上可以跳入并复制任何内容(我尝试添加越来越多的文件以使其进行编译,但没有成功)。我在下面添加了一个最小的示例(处理提供的数据),sh
[ProtoMember(16)]
public SensorState RawData
{
    get { return _rawData ?? (_rawData =  new SensorState(this, DateTime.Now, new Dictionary<DateTime, float>(), "", true, null)); }
    private set { _rawData = value; }
}
[ProtoMember(16)]
private SensorState _rawData;
[ProtoMember(12)]
private SensorState _currentState;