2010-07-30 136 views
23

我在嘗試對發送到我的WCF方法的Stream對象執行stream.Length時收到錯誤。Stream.Length拋出NotSupportedException

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

如何獲得流的長度?任何例子?

+0

Stream類是抽象的,什麼是您所使用的派生Stream類?另外,如果可能,發佈導致問題的代碼? – 2010-07-30 16:46:34

回答

5

你不能總是得到一個流的長度。例如,在網絡流的情況下,找出長度的唯一方法是從它讀取數據直到它關閉。

你想做什麼?您可以從流中讀取數據,直到完全耗盡爲止,將數據複製到MemoryStream中嗎?

+0

我只需要更新perf計數器的字節數。 – 2010-07-30 16:47:22

+4

@ Nevin:這個流還在發生什麼?基本上,如果不通過閱讀來改變狀態,你將無法得到這些信息。 – 2010-07-30 16:50:39

24

Stream.Length只適用於尋求可用的流實現。您通常可以檢查Stream.CanSeek是否爲真。許多流,因爲它們是,是一種性質,它是不可能事先知道長度。

如果您必須知道長度,您可能需要實際緩衝整個流,將其預先加載到內存中。

+1

什麼是'HttpClient.GetStreamAsync(url)'?它將具有長度屬性集,但不是可搜索的。我必須用try-catch來測試Stream.Length屬性的值嗎? – 2017-10-08 16:18:14

4

如果不支持查找,並不總是可以獲得流的長度。請參閱Stream class上的例外表。例如,連接到另一個進程(網絡流,標準輸出等)的流可以產生任意數量的輸出,這取決於另一個進程是如何編寫的,而且框架無法弄清楚有很多數據。

在一般情況下,您只需要讀取所有數據直到流結束,然後確定您已閱讀了多少。

0

TcpClient.EndRead()應該返回流中的字節數。

- 編輯,當然你需要使用一個TCP流

6

我使用WCF服務時遇到了同樣的問題。我需要獲取POST消息的內容,並在我的方法中使用Stream參數來獲取消息正文的內容。一旦我得到流,我想一次讀取它的內容,並且需要知道我需要什麼大小的字節數組。所以,在分配數組時,我會調用System.IO.Stream.Length並獲取OP提到的異常。您是否需要知道流的長度,以便可以讀取整個流的內容? 實際上,您可以使用System.IO.StreamReader將流的全部內容讀取到字符串中。如果你仍然需要知道你的流的大小,你可以得到結果字符串的長度。下面是我如何解決這個問題的代碼:

[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

這是我做的:

// 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

警告:如果文件大小可能超過2 GB(〜'int.MaxValue'),請爲'totalBytesRead'使用'long'類型。 – 2014-10-29 13:56:42

相關問題