5

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

4

2 回答 2

3

您不必读取文件中的所有数据来附加数据。

您可以在附加模式下打开它并写入数据。

var fileStream = File.Open(fileName, FileMode.Append, FileAccess.Write, FileShare.Read);
var binaryWriter = new BinaryWriter(fileStream);
binaryWriter.Write(data);
于 2012-07-16T06:52:48.607 回答
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]);
    }
}

然而!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; } }
}

然后:

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);
    }
}
于 2012-07-16T08:46:07.290 回答