C# 使用BinaryFormatter追加到文件

C# 使用BinaryFormatter追加到文件,c#,serialization,binaryfiles,C#,Serialization,Binaryfiles,我正在使用这个代码 for (int i = 0; i < 3; ++i) { List<int> tl = new List<int>(); tl.Add(5); tl.Add(4); using (var fileStream = new FileStream(@"C:\file.dat", FileMode.Append)) { var bF

我正在使用这个代码

    for (int i = 0; i < 3; ++i)
    {
        List<int> tl = new List<int>();
        tl.Add(5);
        tl.Add(4);
        using (var fileStream = new FileStream(@"C:\file.dat", FileMode.Append))
        {
            var bFormatter = new BinaryFormatter();
            bFormatter.Serialize(fileStream, tl);
            //fileStream.Close();
        }

        var list = new List<int>();

        using (var fileStream = new FileStream(@"C:\file.dat", FileMode.Open))
        {
            var bFormatter = new BinaryFormatter();
            //while (fileStream.Position != fileStream.Length)
            //{
            //     list.Add((int)bFormatter.Deserialize(fileStream));
            //}
            list = (List<int>)bFormatter.Deserialize(fileStream);
            //fileStream.Close();
        }
    }
for(int i=0;i<3;++i)
{
List tl=新列表();
tl.Add(5);
tl.Add(4);
使用(var fileStream=newfilestream(@“C:\file.dat”,FileMode.Append))
{
var bFormatter=new BinaryFormatter();
序列化(fileStream,tl);
//fileStream.Close();
}
var list=新列表();
使用(var fileStream=newfilestream(@“C:\file.dat”,FileMode.Open))
{
var bFormatter=new BinaryFormatter();
//while(fileStream.Position!=fileStream.Length)
//{
//添加((int)bFormatter.Deserialize(fileStream));
//}
list=(list)bFormatter.反序列化(fileStream);
//fileStream.Close();
}
}
我预计.dat文件将被删除

54544

但它只是

5.4

此代码还返回

5.4

List tl=newlist();
tl.Add(5);
tl.Add(4);
使用(var fileStream=newfilestream(@“C:\file.dat”,FileMode.Append))
{
var bFormatter=new BinaryFormatter();
序列化(fileStream,tl);
}
tl.Clear();
tl.Add(3);
tl.Add(2);
使用(var fileStream=newfilestream(@“C:\file.dat”,FileMode.Append))
{
var bFormatter=new BinaryFormatter();
序列化(fileStream,tl);
}
var list=新列表();
使用(var fileStream=newfilestream(@“C:\file.dat”,FileMode.Open))
{
var bFormatter=new BinaryFormatter();
list=(list)bFormatter.反序列化(fileStream);
}
看起来它只对附加的第一部分进行反序列化

为什么数据不附加

更新: 因此,解决方案是:

        var list = new List<int>();

        using (var fileStream = new FileStream(@"C:\file.dat", FileMode.Open))
        {
            var bFormatter = new BinaryFormatter();
            while (fileStream.Position != fileStream.Length)
            {
                var t = (List<int>)(bFormatter.Deserialize(fileStream));
                list.AddRange(t);
            }
        }
var list=newlist();
使用(var fileStream=newfilestream(@“C:\file.dat”,FileMode.Open))
{
var bFormatter=new BinaryFormatter();
while(fileStream.Position!=fileStream.Length)
{
var t=(List)(bFormatter.Deserialize(fileStream));
列表。添加范围(t);
}
}

您正在添加三个整数列表,一个接一个,并且只回读第一个整数。我认为您的意图可能是附加到(单个)现有列表中,在这种情况下,您必须

  • 把你的清单读回记忆
  • 添加您的新元素
  • 以覆盖(非附加)模式将列表写回文件

  • BinaryFormatter
    未列为可追加。实际上,在到达EOF(并手动合并)之前,通常可以多次进行反序列化,但是:还有其他序列化程序是显式设计为可追加的。例如,协议缓冲区是一种可追加的格式:串联与合并相同。进一步:如果外部元素是一个列表,那么添加到文件与添加到composes列表是相同的

    使用protobuf net,这只是:

    for (int i = 0; i < 3; ++i)
    {
        List<int> tl = new List<int>();
        tl.Add(5);
        tl.Add(4);
        using (var fileStream = new FileStream(@"C:\file.dat", FileMode.Append))
        {
            Serializer.Serialize(fileStream, tl);
        }
    
        using (var fileStream = new FileStream(@"C:\file.dat", FileMode.Open))
        {
            list = Serializer.Deserialize<List<int>>(fileStream);
        }
    }
    
    for(int i=0;i<3;++i)
    {
    List tl=新列表();
    tl.Add(5);
    tl.Add(4);
    使用(var fileStream=newfilestream(@“C:\file.dat”,FileMode.Append))
    {
    Serializer.Serialize(fileStream,tl);
    }
    使用(var fileStream=newfilestream(@“C:\file.dat”,FileMode.Open))
    {
    list=序列化程序。反序列化(fileStream);
    }
    }
    

    在每次循环迭代结束时,
    list
    (即反序列化后)有2个、4个、6个元素。

    如Marc Gravel所述,
    BinaryFormatter
    是不可追加的,这意味着每次需要修改文件时都需要重新序列化

    例如:

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Runtime.Serialization.Formatters.Binary;
    
    class Program
    {
        const string file = @"C:\temp\file.dat";
    
        static void Main()
        {
            for (int i = 0; i < 3; ++i)
            {
                List<int> tl = new List<int>();
                tl.Add(5);
                tl.Add(4);
    
                AppendToDisk(tl);
            }
    
            var list = ReadFromDisk<int>();
    
            foreach (var item in list)
            {
                Console.Write(item);
            }
        }
    
        private static void AppendToDisk<T>(IEnumerable<T> collection)
        {
            var existing = ReadFromDisk<T>().ToList();
    
            existing.AddRange(collection);
    
            PersistToDisk(existing);
        }
    
        private static void PersistToDisk<T>(ICollection<T> value)
        {
            if (!File.Exists(file))
            {
                using (File.Create(file)) { };
            }
    
            var bFormatter = new BinaryFormatter();
            using (var stream = File.OpenWrite(file))
            {
                bFormatter.Serialize(stream, value);
            }
        }
    
        private static ICollection<T> ReadFromDisk<T>()
        {
            if (!File.Exists(file)) return Enumerable.Empty<T>().ToArray();
    
            var bFormatter = new BinaryFormatter();
            using (var stream = File.OpenRead(file))
            {
                return (ICollection<T>)bFormatter.Deserialize(stream);
            }
        }
    }
    
    使用系统;
    使用System.Collections.Generic;
    使用System.IO;
    使用System.Linq;
    使用System.Runtime.Serialization.Formatters.Binary;
    班级计划
    {
    常量字符串文件=@“C:\temp\file.dat”;
    静态void Main()
    {
    对于(int i=0;i<3;++i)
    {
    List tl=新列表();
    tl.Add(5);
    tl.Add(4);
    追加磁盘(tl);
    }
    var list=ReadFromDisk();
    foreach(列表中的变量项)
    {
    控制台。写入(项);
    }
    }
    私有静态void AppendToDisk(IEnumerable集合)
    {
    var existing=ReadFromDisk().ToList();
    现有.AddRange(集合);
    PersistToDisk(现有);
    }
    私有静态void persistDisk(ICollection值)
    {
    如果(!File.Exists(File))
    {
    使用(File.Create(File)){};
    }
    var bFormatter=new BinaryFormatter();
    使用(var stream=File.OpenWrite(File))
    {
    序列化(流、值);
    }
    }
    私有静态ICollection ReadFromDisk()
    {
    如果(!File.Exists(File))返回Enumerable.Empty().ToArray();
    var bFormatter=new BinaryFormatter();
    使用(var stream=File.OpenRead(File))
    {
    返回(ICollection)bFormatter.反序列化(流);
    }
    }
    }
    
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Runtime.Serialization.Formatters.Binary;
    
    class Program
    {
        const string file = @"C:\temp\file.dat";
    
        static void Main()
        {
            for (int i = 0; i < 3; ++i)
            {
                List<int> tl = new List<int>();
                tl.Add(5);
                tl.Add(4);
    
                AppendToDisk(tl);
            }
    
            var list = ReadFromDisk<int>();
    
            foreach (var item in list)
            {
                Console.Write(item);
            }
        }
    
        private static void AppendToDisk<T>(IEnumerable<T> collection)
        {
            var existing = ReadFromDisk<T>().ToList();
    
            existing.AddRange(collection);
    
            PersistToDisk(existing);
        }
    
        private static void PersistToDisk<T>(ICollection<T> value)
        {
            if (!File.Exists(file))
            {
                using (File.Create(file)) { };
            }
    
            var bFormatter = new BinaryFormatter();
            using (var stream = File.OpenWrite(file))
            {
                bFormatter.Serialize(stream, value);
            }
        }
    
        private static ICollection<T> ReadFromDisk<T>()
        {
            if (!File.Exists(file)) return Enumerable.Empty<T>().ToArray();
    
            var bFormatter = new BinaryFormatter();
            using (var stream = File.OpenRead(file))
            {
                return (ICollection<T>)bFormatter.Deserialize(stream);
            }
        }
    }