I have a question from a piece of code from the book:
Programming in C#
Exam 70-483
Here's the code:
WebRequest request = WebRequest.Create(“http://www.microsoft.com”);
WebResponse response = request.GetResponse();
StreamReader responseStream = new StreamReader(response.GetResponseStream());
string responseText = responseStream.ReadToEnd();
Console.WriteLine(responseText); // Displays the HTML of the website
response.Close();
My question is that why is the responseStream not closed in this example? Why is just the response object closed?
Calling WebResponse.Close implicity closes the response stream.
Taken from here - http://msdn.microsoft.com/en-us/library/system.net.webresponse.close(v=vs.110).aspx
The Close method cleans up the resources used by a WebResponse and closes the underlying stream by calling the Stream.Close method.
As nsgocev said, the docs say that calling Close on the WebResponse closes the underlying stream. So there's no point trying to close it again.
But I couldn't help responding and pointing out that the code in the example does nothing to protect itself from resource leaks. If an exception occurs, whether in your code or in the communication with the remote web server, the response won't get closed and the underlying stream won't be released, which means the TCP socket probably won't be released, etc.
At the very least,the code should take advantage of the "using" syntactical sugar (which the compiler expands into try/finally) to protect itself and guarantee that the resources are released:
using( WebRequest request = WebRequest.Create( “http://www.microsoft.com” ) )
{
using( WebResponse response = request.GetResponse() )
{
StreamReader responseStream = new StreamReader( response.GetResponseStream() );
string responseText = responseStream.ReadToEnd();
Console.WriteLine( responseText ); // Displays the HTML of the website
}
}
Related
This question already has answers here:
Upload file and download file from FTP
(3 answers)
Closed 4 years ago.
i need to change the logic in an old system and im trying to get the downloading file to work, any ideas? i need to download the files using ftp in c# this is the code i found but i need to get that into a file instead of a stream
// Get the object used to communicate with the server.
FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://192.168.1.52/Odt/"+fileName+".dat");
request.Method = WebRequestMethods.Ftp.DownloadFile;
// This example assumes the FTP site uses anonymous logon.
request.Credentials = new NetworkCredential ("anonymous","janeDoe#contoso.com");
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
Stream responseStream = response.GetResponseStream();
StreamReader reader = new StreamReader(responseStream);
Console.WriteLine(reader.ReadToEnd());
Console.WriteLine("Download Complete, status {0}", response.StatusDescription);
reader.Close();
response.Close();
The suggestion from commenter Ron Beyer isn't bad, but because it involves decoding and re-encoding the text, there is a risk of data loss.
You can download the file verbatim by simply copying the request response stream to a file directly. That would look something like this:
// Some file name, initialized however you like
string fileName = ...;
using (Stream responseStream = response.GetResponseStream())
using (Stream fileStream = File.OpenWrite(filename))
{
responseStream.CopyTo(fileStream);
}
Console.WriteLine("Download Complete, status {0}", response.StatusDescription);
response.Close();
App is talking to a REST service.
Fiddler shows full good XML response coming in as the Apps response
The App is in French Polynesia and an identical copy in NZ works so the prime suspect seemed encoding but we have checked that out and came up empty handed.
Looking at the output string (UTF8 encoding) from the stream reader you can see where it has been truncated. It is in an innocuous piece of xml. The downstream error on an XmlDocument object claims to have an encountered an unexpected end of file while loading the string into an XML Document object which is fair enough.
The truncation point is
ns6:sts-krn>1&
which is part of
ns6:sts-krn>1</ns6:sts-krn><
Is there any size limitation on the response string or some other parameter that we should check.
I am all out of ideas. Code Supplied as requested.
Stream streamResponse = response.GetResponseStream();
StringBuilder sb = new StringBuilder();
Encoding encode = Encoding.GetEncoding("utf-8");
if (streamResponse != null)
{
StreamReader readStream = new StreamReader(streamResponse, encode);
while (readStream.Peek() >= 0)
{
sb.Append((char)readStream.Read());
}
streamResponse.Close();
}
You need to be using using blocks:
using (WebResponse response = request.GetResponse())
{
using (Stream streamResponse = response.GetResponseStream())
{
StringBuilder sb = new StringBuilder();
if (streamResponse != null)
{
using (StreamReader readStream = new StreamReader(streamResponse, Encoding.UTF8))
{
sb.Append(readStream.ReadToEnd());
}
}
}
}
This will ensure that your WebResponse, Stream, and StreamReader all get cleaned up, regardless of whether there are any exceptions.
The reasoning that led me to think about using blocks was:
Some operation was not completed
There were no try/catch blocks hiding exceptions, so if the operation wasn't completed due to exceptions, we would know about it.
There were objects which implement IDisposable which were not in using blocks
Conclusion: try implementing the using blocks to see if disposing the objects will cause the operation to complete.
I added this because the reasoning is actually quite general. The same reasoning works for "my mail message doesn't get sent for two minutes". In that case, the operation which isn't completed is "send email" and the instances are the SmtpClient and MailMessage objects.
An easier way to do this would be:
string responseString;
using (StreamReader readStream = new StreamReader(streamResponse, encode))
{
responseString = readStream.ReadToEnd();
}
For debugging, I would suggest writing that response stream to a file so that you can see exactly what was read. In addition, you might consider using a single byte encoding (like ISO-8859-1) to read the data and write to the file.
You should check the response.ContentType property to see if some other text encoding is used.
I want to convert stream data from response stream into a custom object.
I want to convert respose stream into custom object,I am following these steps.
My code is as follows.
myMethod()
{
state s = new state();
Stream receiveStream;
StreamReader readStream;
HttpWebRequest request;
HttpWebResponse response;
try
{
request = (HttpWebRequest)WebRequest.Create (url);
request.Method = "GET";
request.ContentType = "application/json";
response = (HttpWebResponse)request.GetResponse ();
receiveStream = response.GetResponseStream();
readStream = new StreamReader(receiveStream);
Console.WriteLine (readStream.ReadToEnd());
serializer = new DataContractJsonSerializer(typeof(state));
s = serializer.ReadObject(readStream.BaseStream)as state;
Console.Write(s.name+"\n");
response.Close ();
readStream.Close ();
}
catch (Exception ex)
{
}
}
Object s returning nothing.
Can anyone help me?
The trouble is that you're trying to deserialize an object when you've already read all the data from it just beforehand:
readStream = new StreamReader(receiveStream);
Console.WriteLine (readStream.ReadToEnd());
After those line, the stream will be empty, so there's nothing to deserialize. Get rid of those lines (then use receiveStream below), and you may well find it just works.
Additionally, a few suggestions:
Rather than closing streams explicitly, use using statements
Add a using statement for the response itself, as that implements IDisposable
Keep the scope of each variable as small as it can be, assigning a value at the point of declaration
It's rarely a good idea to catch Exception, and it's almost never a good idea to just swallow exceptions in the way that you are doing, with no logging etc
Follow .NET naming conventions, where state would be State (and possibly make the name a bit more descriptive anyway)
Use a cast rather than as - see my blog post on the topic for reasons
Okay so let's say I have a program which makes a WebRequest and gets a WebResponse, and uses that WebResponse for a StreamReader in a using statement, which obviously gets disposed of after, but what about the WebResponse stream? For example:
WebResponse response = request.GetResponse();
using(StreamReader reader = new StreamReader(response.GetResponseStream()))
{
x = reader.ReadToEnd();
}
So obviously the StreamReader will get disposed after, and all resources devoted to it, but what about the Response Stream from response? Does that? Or should I do it like this:
WebResponse response = request.GetResponse();
using(Stream stream = response.GetResponseStream())
{
using(StreamReader reader = new StreamReader(stream))
{
x = reader.ReadToEnd();
}
}
Thanks
StreamReader assumes ownership of the Stream that you pass to its constructor. In other words, when you dispose the StreamReader object it will automatically also dispose the Stream object that you passed. That's very convenient and exactly what you want, simplifying the code to:
using (var response = request.GetResponse())
using (var reader = new StreamReader(response.GetResponseStream()))
{
x = reader.ReadToEnd();
}
When I use Visual Studio 2013's Code Analysis, it claims the use of two 'usings' here will cause Dispose() to be called twice on 'response' and will generate a hidden 'System.ObjectDisposedException'?
warning CA2202: Microsoft.Usage : Object 'response' can be disposed
more than once in method 'xxx'. To avoid generating a
System.ObjectDisposedException you should not call Dispose more than
one time on an object.
Has anyone else seen this?
I need to do program in c# which opens an internet page and after the page finish to load ("done") , I need to take a timestamp to see how much time it took.
How can I do this?
You need something like this:
WebRequest myWebRequest = WebRequest.Create(strURL);
WebResponse myWebResponse = myWebRequest.GetResponse();
Stream ReceiveStream = myWebResponse.GetResponseStream();
Encoding encode = System.Text.Encoding.GetEncoding("utf-8");
StreamReader readStream = new StreamReader( ReceiveStream, encode );
string strResponse=readStream.ReadToEnd();
StreamWriter oSw=new StreamWriter(strFilePath);
oSw.WriteLine(strResponse);
oSw.Close();
readStream.Close();
myWebResponse.Close();
Measure the time before and after the code above to see how much it took.
Thanks,
Flores