C # descargando una página web. Una mejor manera necesaria, uso de CPU alta
Pregunta
Estoy intentando que este código funcione un poco mejor. Sospecho que es el bucle que lee un byte a la vez. No pude encontrar otra forma de hacer esto con la descompresión gzip. La implementación de un StreamReader
está bien, pero devuelve una cadena que no puedo pasar a la secuencia de descompresión.
¿Hay una mejor manera?
byte[] bufffer = null;
List<byte> resourceBytes = new List<byte>();
int byteValue = 0;
WebResource resource = new WebResource();
HttpWebResponse webResponse = null;
try {
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(resourceUri);
webRequest.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip,deflate");
webRequest.Headers.Add(HttpRequestHeader.AcceptCharset, "ISO-8859-1,utf-8;q=0.7,*;q=0.7");
webRequest.UserAgent = agent;
webRequest.Accept = "text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1";
webRequest.Credentials = CredentialCache.DefaultCredentials;
webRequest.Referer = resourceUri.OriginalString;
webRequest.Timeout = 5000;
webResponse = (HttpWebResponse)webRequest.GetResponse();
Stream webStream = webResponse.GetResponseStream();
if (!string.IsNullOrEmpty(webResponse.ContentEncoding)) {
if (webResponse.ContentEncoding.ToLower().Contains("gzip")) {
webStream = new GZipStream(webStream, CompressionMode.Decompress);
}
else if (webResponse.ContentEncoding.ToLower().Contains("deflate")) {
webStream = new DeflateStream(webStream, CompressionMode.Decompress);
}
}
do {
byteValue = webStream.ReadByte();
if (byteValue != -1) {
resourceBytes.Add((byte)byteValue);
}
} while (byteValue != -1);
//Free up resources
webStream.Close();
webResponse.Close();
bufffer = resourceBytes.ToArray();
Solución
Estoy de acuerdo con jmcd en que WebClient sería mucho más simple, en particular WebClient.DownloadData.
refiriéndose a la pregunta real, el problema es que está leyendo bytes individuales, cuando probablemente debería tener un búfer fijo y, por ejemplo, un bucle
int bytesRead;
byte[] buffer = new byte[1024];
while((bytesRead = webStream.Read(buffer, 0, buffer.Length)) > 0) {
// process "bytesRead" worth of data from "buffer"
}
[editar para agregar énfasis] El bit importante es que solo procesa " bytesRead " valor de los datos cada vez; Todo lo que hay más allá es basura.
Otros consejos
Es el Cliente web ¿Clase sin uso para lo que quieres hacer?
Si desea que la respuesta sea una cadena, puede hacerlo.
String ReponseText;
IO.StreamReader ResponseReader = New IO.StreamReader(webStream );
ReponseText= ResponseReader.ReadToEnd();
Si quieres una matriz de bytes real, haz esto (Lo siento, no tengo ganas de convertir a C # para este)
'Declare Array Same size as response
Dim ResponseData(webStream .Length) As Byte
'Read all the data at once
webStream.Read(ResponseData, 0, webStream .Length)