2011-06-02 15 views
7

Para el trabajo, la especificación de mi proyecto es utilizar .Net 2.0, por lo que no aparece la útil función CopyTo más adelante.¿Copia de una secuencia a otra?

Necesito copiar el flujo de respuesta de un HttpWebResponse a otra secuencia (muy probablemente un MemoryStream, pero podría ser cualquier subclase de Stream). Mi táctica habitual ha sido algo así como:

BufferedStream bufferedresponse = new BufferedStream(HttpResponse.GetResponseStream()); 
int count = 0; 
byte[] buffer = new byte[1024]; 
do { 
    count = bufferedresponse.Read(buffer, 0, buffer.Length); 
    target.Write(buffer, 0, count); 
} while (count > 0); 
bufferedresponse.Close(); 

¿Hay formas más eficientes de hacerlo? ¿El tamaño del buffer realmente importa? ¿Cuál es la mejor forma de copiar de una transmisión a otra en .Net 2.0?

P.S. Esto es para descargar imágenes grandes, 200+ MB GIS tif. Por supuesto, la fiabilidad es primordial.

+3

duplicado Posible de [Mejor manera de copiar entre dos instancias Stream] (http://stackoverflow.com/questions/230128/best-way-to-copy-between-two-stream-instances-c) . También la respuesta elegida es lo que estás haciendo actualmente, así que diría que lo estás haciendo correctamente. –

+0

Antes de que mi pregunta se cierre, me gustaría decir que la mía viene con la restricción .Net 2.0. Espero que sea suficiente para mantenerlo abierto, no quiero que se cierren mis preguntas :( –

+0

La pregunta a la que me he vinculado tiene una respuesta usando su método y el método más nuevo de "CopyTo". Vale la pena mencionar que obtendría un mejor rendimiento (si se ajusta a su caso de uso) para esperar que entre toda la secuencia y luego copie la secuencia en trozos más grandes. Pero eso no siempre es lo ideal. –

Respuesta

9

Esta es una función práctica. Y sí, el tamaño del buffer importa. Aumentarlo podría brindarle un mejor rendimiento en archivos grandes.

public static void WriteTo(Stream sourceStream, Stream targetStream) 
{ 
     byte[] buffer = new byte[0x10000]; 
     int n; 
     while ((n = sourceStream.Read(buffer, 0, buffer.Length)) != 0) 
      targetStream.Write(buffer, 0, n); 
} 
1

Usted puede deshacerse de la BufferedStream, sólo es útil si usted está leyendo pequeños trozos de la corriente. Solo obtenga el flujo de respuesta en una variable y use eso:

Stream response = HttpResponse.GetResponseStream(); 

Un buffer que es demasiado pequeño reducirá el rendimiento. Puede usar un buffer más grande, de modo que al menos los datos de un paquete de IP completo se ajusten. Miré alrededor un poco, y 4096 bytes deberían ser suficientes para eso. Realmente puede usar cualquier tamaño de hasta 85 kb, después de eso se asigna en el montón de objetos grandes, lo que debe evitar hacer cuando no hay ninguna razón para ello.

Aparte de eso, es lo más eficiente posible.

2

El tamaño del búfer sí importa. Si está copiando un megabyte de datos de un byte a la vez, por ejemplo, va a hacer 2^20 iteraciones a través del ciclo. Si está copiando 1 kilobyte a la vez, solo realizará 2^10 iteraciones a través del ciclo. Hay una sobrecarga significativa en las llamadas al Read y al Write cuando genera un millón de ellas.

Para leer FileStream, generalmente utilizo un buffer que está entre 64K y 256K. Cualquier cosa inferior a 32K muestra una marcada disminución en el rendimiento, al igual que cualquier cosa superior a 256K. La diferencia entre usar un buffer de 64K y un buffer de 256K no vale la memoria extra. Tenga en cuenta, sin embargo, que esos números están en mi sistema y en mi red. Sus números variarán según el hardware y el sistema operativo.

Para transmisiones de red, debe seleccionar un tamaño de búfer que se mantenga al día con la secuencia de datos entrante. Sugeriría al menos 4 kilobytes, lo que te dará algo de buffer si la escritura se detiene por algún motivo.

0

Puedo pensar de dos maneras.

  1. Compruebe si Stream.MemberWiseClone() se adapta a su deseo. Te da una copia superficial de tu objeto.

  2. Compruebe si esto funciona, si ambos extremos son del tipo de secuencia.

    BufferedStream bs = new BufferedStream ((Stream) memoryStreamObject);

+0

Esos métodos le darán otra forma de acceder a la misma transmisión, para eso propósito, puedes copiar la referencia de la transmisión a otra variable ... – Guffa

Cuestiones relacionadas