2010-03-04 56 views

回答

0

不使用任何内置类,但可以轻松地创建一个具有此类限制的流包装类。

只需将使用这样的:

Stream limitedStream = new LimitedStream(realStream, 10 * 1024 * 1024); // 10MB max 

,然后序列化到这一点。

+0

ok thanq。 因此,如果将10MB的数据写入流并且stil还有一些要被序列化的对象的其他属性会发生什么。它会引发异常吗? – sandhya 2010-03-04 12:00:03

+0

我会写那个流类,当它达到10MB时抛出一个异常,是的。 – 2010-03-04 12:01:57

2

根据序列化程序,可能会独立地将项目放到流的末尾(并且还可以再次读取流)。不是用“纯粹的”xml(由于根元素),但我知道至少有一个支持顺序对象读/写的序列化程序(没有猜测哪个是奖品)。

如果大小是绝对键,那么也许通过MemoryStream去 - 有点像(伪代码)

using(Stream dest = ...) 
using(MemoryStream buffer = new MemoryStream()) 
{ 
    foreach(SomeType obj in items) { 
     buffer.SetLength(0); // reset to empty, but retaining buffer to reduce allocs 
     someSerializer.Serialize(buffer, obj); 

     if(enoughSpace) { 
      // add our item 
      dest.Write(buffer.GetBuffer(), 0, buffer.Length); 
      // TODO: decrement space  
     } else { 
      break; // or new file, whatever 
     } 
    } 
} 

完成任务。这可避免通过完成每个对象到存储器流(尽可能重新使用底层内存)来完成每个对象的写入部分对象,因此只有当您知道它适合时才将数据复制到实际的流中。

下面是使用protobuf-net一个完整的示例:

using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Xml.Serialization; 
using ProtoBuf; 
[XmlType]  // not actually serialized as xml; simply it needs 
class MyData // a way of identifying the members, and it supports 
{    // the Order property via XmlType/XmlElement 
    [XmlElement(Order = 1)] public int Id { get; set; } 
    [XmlElement(Order = 2)] public string Name { get; set; } 
} 
static class Program 
{ 
    static IEnumerable<MyData> GetItems() 
    { 
     Random rand = new Random(); 
     int count = 0; 
     while (true) // an infinite sequence of data; mwahahaahah 
     { 
      yield return new MyData 
      { 
       Id = rand.Next(0, 5000), 
       Name = "Item " + count++ 
      }; 
     } 
    } 
    static void Main() 
    { 
     int space = 2048, count = 0; 
     long checksum = 0; 
     using(Stream dest = File.Create("out.bin")) 
     using(MemoryStream buffer = new MemoryStream()) 
     { 
      foreach (MyData obj in GetItems()) 
      { 
       buffer.SetLength(0); // reset to empty, but retaining buffer to reduce allocs 
       Serializer.SerializeWithLengthPrefix(buffer, obj, PrefixStyle.Base128, 1); 
       int len = (int)buffer.Length; 
       if(buffer.Length <= space) { 
        // add our item 
        dest.Write(buffer.GetBuffer(), 0, len); 
        space -= len; 
        checksum += obj.Id; 
        count++; 
       } else { 
        break; // or new file, whatever 
       } 
      } 
     } 
     Console.WriteLine("Wrote " + count + " objects; chk = " + checksum); 

     using (Stream source = File.OpenRead("out.bin")) 
     { 
      count = 0; 
      checksum = 0; 
      foreach (MyData item in 
       Serializer.DeserializeItems<MyData>(source, PrefixStyle.Base128, 1)) 
      { 
       count++; 
       checksum += item.Id; 
      } 
     } 

     Console.WriteLine("Read " + count + " objects; chk = " + checksum); 
    } 
} 

可能能这种方法与其他串行扩展(如BinaryFormatterDataContractSerializer),但你可能必须写你自己的长度-prefix(写入时),使用它(读取时)并限制数据。不是火箭科学,但不是完全微不足道的。