简体   繁体   中英

Querying serialized object file

Is there anyway to achieve that without loading the whole file into memory? If so, what do you suggest me to do?

Class implementation:

[Serializable()]
public class Car
{
    public string Brand { get; set; }
    public string Model { get; set; }
}

[Serializable()]
public class CarCollection : List<Car>
{
}

Serialization to file:

CarCollection cars = new CarCollection
{
    new Cars{ Brand = "BMW", Model = "7.20" },
    new Cars{ Brand = "Mercedes", Model = "CLK" }
};

using (Stream stream = File.Open("data", FileMode.Create))
{
    BinaryFormatter bin = new BinaryFormatter();
    bin.Serialize(stream, cars);
}

如果您序列化为XML,则可以使用SAX解析器( XmlReader类 ),该解析器将从流中顺序读取。

To deserialize the collection one object at a time, you also need to serialize it one at a time.

Simplest way is to define your own generic class:

public static class StreamSerializer
{
    public static void Serialize<T>(IList<T> list, string filename)
    {
        using (Stream stream = File.Open(filename, FileMode.Create))
        {
            BinaryFormatter bin = new BinaryFormatter();

            // seralize each object separately
            foreach (var item in list)
                bin.Serialize(stream, item);
        }
    }

    public static IEnumerable<T> Deserialize<T>(string filename)
    {
        using (Stream stream = File.Open(filename, FileMode.Open))
        {
            BinaryFormatter bin = new BinaryFormatter();

            // deserialize each object separately, and 
            // return them one at a time

            while (stream.Position < stream.Length)
                yield return (T)bin.Deserialize(stream);
        }
    }
}

Then you can simply write:

CarsCollection cars = new CarsCollection
{
    new Cars{ Brand = "BMW", Model = "7.20" },
    new Cars{ Brand = "Mercedes", Model = "CLK" }
};

// note that you cannot serialize the entire list if
// you want to query without loading - it must be symmetrical

StreamSerializer.Serialize(cars, "data.bin");

// the following expression iterates through objects, processing one 
// at a time. "First" method is a good example because it
// breaks early.

var bmw = StreamSerializer
    .Deserialize<Cars>("data.bin")
    .First(c => c.Brand == "BMW");

A slightly more complex case might be if your CarsCollection belongs to a different class. In that case, you will need to implement ISerializable , but the principle is similar.

On a side note, usual convention is not to name entities in plural (ie Cars should be named Car ).

通常,您可以将某种类型的阅读器(StreamReader,BinaryReader等)与BufferedStream一起使用。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM