如何在磁盘上的序列化文件中附加数据

Dee*_*Dee 5 c#

我有一个用C#编写的程序,该程序将数据序列化为二进制并将其写入磁盘。如果要向此文件添加更多数据,首先必须对整个文件进行反序列化,然后再向其中附加更多序列化的数据。是否可以在不反序列化现有数据的情况下将数据附加到此序列化文件中,以便在整个过程中节省一些时间?

Mar*_*ell 2

现在我们知道(评论)我们正在谈论DataTable/ DataSetvia BinaryFormatter,它变得更加清晰。如果您的目的是让它在现有表中显示为额外的行,那么不行:那是行不通的。您可以做的是追加,但依次反序列化每个表,然后手动合并内容。这可能是你所描述的最好的选择。这是一个仅使用 2 的示例,但显然您会重复反序列化/合并直到 EOF:

var dt = new DataTable();
dt.Columns.Add("foo", typeof (int));
dt.Columns.Add("bar", typeof(string));

dt.RemotingFormat = SerializationFormat.Binary;
var ser = new BinaryFormatter();
using(var ms = new MemoryStream())
{
    dt.Rows.Add(123, "abc");
    ser.Serialize(ms, dt); // batch 1
    dt.Rows.Clear();
    dt.Rows.Add(456, "def");
    ser.Serialize(ms, dt); // batch 2

    ms.Position = 0;

    var table1 = (DataTable) ser.Deserialize(ms);

    // the following is the merge loop that you'd repeat until EOF
    var table2 = (DataTable) ser.Deserialize(ms);
    foreach(DataRow row in table2.Rows) {
        table1.ImportRow(row);
    }

    // show the results
    foreach(DataRow row in table1.Rows)
    {
        Console.WriteLine("{0}, {1}", row[0], row[1]);
    }
}
Run Code Online (Sandbox Code Playgroud)

然而!DataTable就我个人而言,我对和都抱有疑虑BinaryFormatter。如果您知道您的数据是什么,还有其他技术。例如,这可以使用“protobuf”非常简单地完成,因为 protobuf 本质上是可附加的。事实上,您需要做额外的事情才能附加(尽管这也很简单):

[ProtoContract]
class Foo
{
    [ProtoMember(1)]
    public int X { get; set; }
    [ProtoMember(2)]
    public string Y { get; set; }

}
[ProtoContract]
class MyData
{
    private readonly List<Foo> items = new List<Foo>();
    [ProtoMember(1)]
    public List<Foo> Items { get { return items; } }
}
Run Code Online (Sandbox Code Playgroud)

然后:

var batch1 = new MyData { Items = { new Foo { X = 123, Y = "abc" } } };
var batch2 = new MyData { Items = { new Foo { X = 456, Y = "def" } } };
using(var ms = new MemoryStream())
{
    Serializer.Serialize(ms, batch1);
    Serializer.Serialize(ms, batch2);
    ms.Position = 0;
    var merged = Serializer.Deserialize<MyData>(ms);
    foreach(var row in merged.Items) {
        Console.WriteLine("{0}, {1}", row.X, row.Y);
    }
}
Run Code Online (Sandbox Code Playgroud)