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

时间:2012-07-16 06:46:32

标签: c#

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

2 个答案:

答案 0 :(得分:2)

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

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

var fileStream = File.Open(fileName, FileMode.Append, FileAccess.Write, FileShare.Read);
var binaryWriter = new BinaryWriter(fileStream);
binaryWriter.Write(data);

答案 1 :(得分:2)

现在我们知道(评论)我们正在通过DataTable谈论DataSet / 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]);
    }
}

然而!我个人对DataTableBinaryFormatter都有疑虑。如果您知道您的数据是什么,还有其他技术。例如,这可以通过“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);
    }
}