2010-07-30 29 views
23

Recibo un error al intentar stream.Length en un objeto Stream enviado a mi método WCF.Stream.Length throws NotSupportedException

Unhandled Exception! 
Error ID: 0 
Error Code: Unknown 
Is Warning: False 
Type: System.NotSupportedException 
Stack: at System.ServiceModel.Dispatcher.StreamFormatter.MessageBodyStream.get_Length() 

¿Cómo se obtiene la duración de la transmisión? algún ejemplo?

+0

La corriente es abstracto, ¿cuál es la clase Stream derivado que está utilizando? Además, publique el código que está causando el problema si es posible. –

Respuesta

5

No siempre se puede obtener la longitud de una secuencia. En el caso de una transmisión en red, la única forma de conocer la longitud es leer datos de ella hasta que se cierre, por ejemplo.

¿Qué estás tratando de hacer? ¿Podría leer de la transmisión hasta que esté agotada, copiando los datos en un MemoryStream sobre la marcha?

+0

Solo necesito el número de bytes para actualizar un contador de rendimiento. –

+4

@Nevin: ¿Qué más está pasando con la transmisión? Básicamente, no podrá obtener esta información sin cambiar el estado leyendo de ella. –

24

Stream.Length solo funciona en implementaciones de Stream donde la búsqueda está disponible. Por lo general, puede verificar para ver si Stream.CanSeek es verdadero. Muchas secuencias, dado que están siendo transmitidas por streaming, son de una naturaleza en la que es imposible conocer la longitud por adelantado.

Si debe conocer la longitud, es posible que necesite almacenar en búfer la secuencia completa y cargarla en la memoria con anticipación.

+1

¿Qué hay sobre 'HttpClient.GetStreamAsync (url)'? Tendrá el conjunto de propiedades de longitud pero no es buscable. ¿Debo entonces probar el valor del atributo Stream.Length con try-catch? –

4

No siempre es posible obtener la longitud de una secuencia si no es compatible con la búsqueda. Consulte la tabla de excepciones en el Stream class.

Por ejemplo, una secuencia conectada a otro proceso (flujo de red, salida estándar, etc.) puede producir cualquier cantidad de salida, dependiendo de cómo se escriba el otro proceso, y no hay forma de que el marco averigüe cómo mucha información que hay

En el caso general, solo tiene que leer todos los datos hasta el final de la transmisión y luego averiguar cuánto ha leído.

0

TcpClient.EndRead() debe devolver el número de bytes que están en la secuencia.

--Editar, por supuesto, hay que estar utilizando una corriente TCP

6

me encontré con este mismo problema al utilizar los servicios de WCF. Necesitaba obtener el contenido de un mensaje POST, y estaba usando un argumento Stream en mi método para obtener el contenido del cuerpo del mensaje. Una vez que obtuve la transmisión, quería leer sus contenidos de una sola vez, y necesitaba saber qué tamaño de matriz de bytes necesitaría. Entonces, en la asignación de la matriz, llamaría a System.IO.Stream.Length y obtendría la excepción mencionada por el OP. ¿Es la razón por la que necesita saber la longitud de la transmisión para que pueda leer el contenido de la secuencia completa? Puede leer todo el contenido de la secuencia en una cadena utilizando System.IO.StreamReader. Si aún necesita saber el tamaño de su transmisión, puede obtener la longitud de la cadena resultante. Aquí está el código de cómo resolví este problema:

[OperationContract] 
    [WebInvoke(UriTemplate = "authorization")] 
    public Stream authorization(Stream body) 
    { 
     // Obtain the token from the body 
     StreamReader bodyReader = new StreamReader(body); 
     string bodyString= bodyReader.ReadToEnd(); 
     int length=bodyString.Length; // (If you still need this.) 
     // Do whatever you want to do with the body contents here. 
    } 
3

Esto es lo que hago: Clase

// Return the length of a stream that does not have a usable Length property 
    public static long GetStreamLength(Stream stream) 
    { 
     long originalPosition = 0; 
     long totalBytesRead = 0; 

     if (stream.CanSeek) 
     { 
      originalPosition = stream.Position; 
      stream.Position = 0; 
     } 

     try 
     { 
      byte[] readBuffer = new byte[4096]; 

      int bytesRead; 

      while ((bytesRead = stream.Read(readBuffer, 0, 4096)) > 0) 
      { 
       totalBytesRead += bytesRead; 
      } 

     } 
     finally 
     { 
      if (stream.CanSeek) 
      { 
       stream.Position = originalPosition; 
      } 
     } 

     return totalBytesRead; 
    } 
+1

Advertencia: utilice el tipo 'long' para' totalBytesRead' en caso de que su tamaño de archivo supere los 2 GB (~ 'int.MaxValue'). –

Cuestiones relacionadas