2011-08-04 10 views
5

Tengo una transmisión que contiene muchos datos. Quiero exponer solo una parte de esos datos en otra secuencia. La información que quiero extraer a menudo puede superar los 100mb. Como ya tengo stream con los datos que contiene, me parece un desperdicio copiar esos datos a otra transmisión y devolverlos. Lo que estoy buscando es una forma de referenciar los datos en la primera secuencia mientras se controla a qué cantidad puede hacer referencia la segunda secuencia. Es posibleCómo exponer una subsección de mi transmisión a un usuario

Respuesta

4

Debe crear su propia clase Stream que valide su posición y devuelva el subconjunto deseado.

No conozco ninguna clase incorporada que lo haga.

+0

Así que ahora comienza mi tarea ... – QueueHammer

0

¿Qué tienes miedo de duplicar? Dudo que tengas algo de súper desempeño crítico, analiza tu Stream sobre la marcha y usas MemoryStream hasta que encuentres que necesitas algo más.

+4

estaría copiando cientos de mesgs valor de los datos, y no quiero que copiar a otro lugar en la memoria. Específicamente si la persona va a solicitar múltiples secciones de cientos de megas. Además de no temer a la duplicación, es una práctica de programación reutilizar otras clases si existen. – QueueHammer

0

Parece que el proyecto StreamMuxer se creó con un propósito similar en mente.

+0

Esto se ve bien. Deseo que Code Project haya trabajado con Git Hub. Probablemente un leve conflicto de intereses. – QueueHammer

3

Hay una buena implementación de esto por Mark Gravell detailed here. El código escrito existe:

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