2011-08-04 55 views
5

我有一個包含許多數據的流。我想在另一個流中公開一部分數據。我想提取的數據通常可能超過100MB。由於我已經將流中的數據進行了流式處理,所以將這些數據複製到另一個流並返回它似乎是一種浪費。即時通訊尋找的是一種方法來引用第一個數據流中的數據,同時控制第二個數據流可以引用多少數據。這是可能的嗎如何將我的流的子部分展示給用戶

回答

4

您需要製作自己的Stream類來驗證其位置並返回所需的子集。

我不知道有這樣做的任何內置類。

+0

所以現在我的任務開始了... – QueueHammer

0

什麼是你害怕重複?我懷疑你有什麼超級性能的關鍵,立即解析你的Stream並使用MemoryStream,直到你發現你需要別的東西。

+4

我會複製數百MESGS價值的數據,而不願到複製到另一個地方,在內存中。具體而言,如果該人要請求數百兆部分。除了它不怕重複外,是一種編程來重用其他類的實踐,如果它們存在的話。 – QueueHammer

0

看起來像StreamMuxer項目創建時有着類似的目的。

+0

這看起來不錯。我希望Code Project能夠與Git Hub合作。可能有輕微的利益衝突。 – QueueHammer

3

Mark Gravell detailed here有很好的實現。代碼貼有:

using System.IO; 
using System; 
static class Program 
{ 

// shows that we can read a subset of an existing stream... 
    static void Main() 
    { 
     byte[] buffer = new byte[255]; 
     for (byte i = 0; i < 255; i++) 
     { 
      buffer[i] = i; 
     } 
     using(MemoryStream ms = new MemoryStream(buffer)) 
     using (SubStream ss = new SubStream(ms, 10, 200)) 
     { 
      const int BUFFER_SIZE = 17; // why not... 
      byte[] working = new byte[BUFFER_SIZE]; 
      int read; 
      while ((read = ss.Read(working, 0, BUFFER_SIZE)) > 0) 
      { 
       for (int i = 0; i < read; i++) 
       { 
        Console.WriteLine(working[i]); 
       } 
      } 
     } 
    } 
} 

class SubStream : Stream 
{ 
    private Stream baseStream; 
    private readonly long length; 
    private long position; 
    public SubStream(Stream baseStream, long offset, long length) 
    { 
     if (baseStream == null) throw new ArgumentNullException("baseStream"); 
     if (!baseStream.CanRead) throw new ArgumentException("can't read base stream"); 
     if (offset < 0) throw new ArgumentOutOfRangeException("offset"); 

     this.baseStream = baseStream; 
     this.length = length; 

     if (baseStream.CanSeek) 
     { 
      baseStream.Seek(offset, SeekOrigin.Current); 
     } 
     else 
     { // read it manually... 
      const int BUFFER_SIZE = 512; 
      byte[] buffer = new byte[BUFFER_SIZE]; 
      while (offset > 0) 
      { 
       int read = baseStream.Read(buffer, 0, offset < BUFFER_SIZE ? (int) offset : BUFFER_SIZE); 
       offset -= read; 
      } 
     } 
    } 
    public override int Read(byte[] buffer, int offset, int count) 
    { 
     CheckDisposed(); 
     long remaining = length - position; 
     if (remaining <= 0) return 0; 
     if (remaining < count) count = (int) remaining; 
     int read = baseStream.Read(buffer, offset, count); 
     position += read; 
     return read; 
    } 
    private void CheckDisposed() 
    { 
     if (baseStream == null) throw new ObjectDisposedException(GetType().Name); 
    } 
    public override long Length 
    { 
     get { CheckDisposed(); return length; } 
    } 
    public override bool CanRead 
    { 
     get { CheckDisposed(); return true; } 
    } 
    public override bool CanWrite 
    { 
     get { CheckDisposed(); return false; } 
    } 
    public override bool CanSeek 
    { 
     get { CheckDisposed(); return false; } 
    } 
    public override long Position 
    { 
     get { 
      CheckDisposed(); 
      return position; 
     } 
     set { throw new NotSupportedException(); } 
    } 
    public override long Seek(long offset, SeekOrigin origin) 
    { 
     throw new NotSupportedException(); 
    } 
    public override void SetLength(long value) 
    { 
     throw new NotSupportedException(); 
    } 
    public override void Flush() 
    { 
     CheckDisposed(); baseStream.Flush(); 
    } 
    protected override void Dispose(bool disposing) 
    { 
     base.Dispose(disposing); 
     if (disposing) 
     { 
      if (baseStream != null) 
      { 
       try { baseStream.Dispose(); } 
       catch { } 
       baseStream = null; 
      } 
     } 
    } 
    public override void Write(byte[] buffer, int offset, int count) 
    { 
     throw new NotImplementedException(); 
    } 
} 
相關問題