2010-03-04 55 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(寫入時),使用它(讀取時)並限制數據。不是火箭科學,但不是完全微不足道的。