4

私はこのコードを使用しています

    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();
        }
    }

私は.datファイルが

5 4 5 4 5 4

しかし、それだけです

5 4

また、このコードも戻ります

5 4

        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);
        }

        tl.Clear();
        tl.Add(3);
        tl.Add(2);
        using (var fileStream = new FileStream(@"C:\file.dat", FileMode.Append))
        {
            var bFormatter = new BinaryFormatter();
            bFormatter.Serialize(fileStream, tl);
        }

        var list = new List<int>();

        using (var fileStream = new FileStream(@"C:\file.dat", FileMode.Open))
        {
            var bFormatter = new BinaryFormatter();
            list = (List<int>)bFormatter.Deserialize(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);
            }
        }
4

3 に答える 3

3

int の 3 つのリストを次々に追加し、最初の 1 つだけを読み戻しています。あなたの意図は、(単一の)既存のリストに追加することだと思います。その場合は、

  1. リストをメモリに読み戻します
  2. 新しい要素を追加する
  3. リストを上書き (追加ではない) モードでファイルに書き戻します。
于 2013-07-08T12:01:35.897 に答える
1

BinaryFormatter追加可能としてリストされていません。たまたま、EOFに到達するまで(および手動でマージするまで)複数回デシリアライズすることで通常は回避できますが、追加可能になるよう明示的に設計されたシリアライザーは他にもあります。たとえば、プロトコル バッファは追加可能な形式です。連結はマージと同じです。さらに、外側の要素がリストの場合、ファイルへの追加は構成リストへの追加と同じです。

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);
    }
}

各ループ反復の終わりlist(つまり、デシリアライズ後) には、2 つ、次に 4 つ、次に 6 つの要素があります。

于 2013-07-08T12:19:07.757 に答える
1

Marc GravellBinaryFormatterが言及したように、ファイルを変更する必要があるたびに再シリアル化する必要があることを意味します。

例:

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);
        }
    }
}
于 2013-07-08T12:25:13.447 に答える