簡體   English   中英

C# 中的錯誤“此流不支持搜索操作”

[英]Error "This stream does not support seek operations" in C#

我正在嘗試使用byte流從 url 獲取圖像。 但我收到此錯誤消息:

此流不支持查找操作。

這是我的代碼:

byte[] b;
HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create(url);
WebResponse myResp = myReq.GetResponse();

Stream stream = myResp.GetResponseStream();
int i;
using (BinaryReader br = new BinaryReader(stream))
{
    i = (int)(stream.Length);
    b = br.ReadBytes(i); // (500000);
}
myResp.Close();
return b;

伙計們,我做錯了什么?

你可能想要這樣的東西。 要么檢查長度失敗,要么 BinaryReader 在幕后進行搜索。

HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create(url);
WebResponse myResp = myReq.GetResponse();

byte[] b = null;
using( Stream stream = myResp.GetResponseStream() )
using( MemoryStream ms = new MemoryStream() )
{
  int count = 0;
  do
  {
    byte[] buf = new byte[1024];
    count = stream.Read(buf, 0, 1024);
    ms.Write(buf, 0, count);
  } while(stream.CanRead && count > 0);
  b = ms.ToArray();
}

編輯:

我使用反射器檢查過,它是對 stream.Length 的調用失敗了。 GetResponseStream 返回一個 ConnectStream,並且該類的 Length 屬性會引發您看到的異常。 正如其他海報所提到的,您無法可靠地獲得 HTTP 響應的長度,因此這是有道理的。

改用StreamReader

HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create(url);
WebResponse myResp = myReq.GetResponse();

StreamReader reader = new StreamReader(myResp.GetResponseStream());
return reader.ReadToEnd();

(注意 - 以上返回一個String而不是一個字節數組)

您無法可靠地詢問 HTTP 連接的長度。 可以讓服務器提前向您發送長度,但是 (a) 標頭經常丟失,並且 (b) 不能保證它是正確的。

相反,您應該:

  1. 創建傳遞給Stream.Read方法的固定長度byte[]
  2. 創建一個List<byte>
  3. 每次讀取后,調用List.AddRange將固定長度緩沖區的內容附加到字節列表中

請注意,對Read的最后一次調用將返回少於您要求的完整字節數。 確保您只將該字節數附加到您的List<byte>而不是整個byte[] ,否則您將在列表末尾得到垃圾。

如果服務器未在 HTTP 標頭中發送長度規范,則流大小未知,因此您在嘗試使用Length屬性時會收到錯誤消息。

以較小的塊讀取流,直到到達流的末尾。

對於圖像,您根本不需要讀取字節數。 只需這樣做:

Image img = null;
string path = "http://www.example.com/image.jpg";
WebRequest request = WebRequest.Create(path);
req.Credentials = CredentialCache.DefaultCredentials; // in case your URL has Windows auth
WebResponse resp = req.GetResponse();

using( Stream stream = resp.GetResponseStream() ) 
{
    img = Image.FromStream(stream);
    // then use the image
}

也許您應該使用System.Net.WebClient API。 如果已經使用client.OpenRead(url)使用client.DownloadData(URL)

var client = new System.Net.WebClient();
byte[] buffer = client.DownloadData(url);
using (var stream = new MemoryStream(buffer))
{
    ... your code using the stream ...
}

顯然,這會在創建Stream之前下載所有內容,因此可能會違背使用Stream的目的。 webClient.DownloadData("https://your.url")獲取一個字節數組,然后您可以將其轉換為MemoryStream

無法從流中讀取流的長度,因為接收方不知道發送方將發送多少字節。 嘗試將協議放在 http 之上,並將長度作為流中的第一項發送。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM