Using C#, I was surprised how complicated it seemed to preserve binary info from a stream. I'm trying to download a PNG datafile using the WebRequest class, but just transfering the resulting Stream to a file, without corrupting it was more verbose than I thought. First, just using StreamReader and StreamWriter was no good as the ReadToEnd() function returns a string, which effectivly doubles the size of the PNG file (probably due to the UTF conversion)
So my question is, do I really have to write all this code, or is there a cleaner way of doing it?
Stream srBytes = webResponse.GetResponseStream();
// Write to file
Stream swBytes = new FileStream("map(" + i.ToString() + ").png",FileMode.Create,FileAccess.Write);
int count = 0;
byte[] buffer = new byte[4096];
do
{
count = srBytes.Read(buffer, 0, buffer.Length);
swBytes.Write(buffer, 0, count);
}
while (coun开发者_StackOverflow中文版t != 0);
swBytes.Close();
Using StreamReader
/StreamWriter
is definitely a mistake, yes - because that's trying to load the file as text, which it's not.
Options:
- Use
WebClient.DownloadFile
as SLaks suggested - In .NET 4, use
Stream.CopyTo(Stream)
to copy the data in much the same way as you've got here Otherwise, write your own utility method to do the copying, then you only need to do it once; you could even write this as an extension method, which means when you upgrade to .NET 4 you can just get rid of the utility method and use the built-in one with no change to the calling code:
public static class StreamExtensions { public static void CopyTo(this Stream source, Stream destination) { if (source == null) { throw new ArgumentNullException("source"); } if (destination == null) { throw new ArgumentNullException("destination"); } byte[] buffer = new byte[8192]; int bytesRead; while ((bytesRead = source.Read(buffer, 0, buffer.Length)) > 0) { destination.Write(buffer, 0, bytesRead); } } }
Note that you should be using using
statements for the web response, response stream and output stream in order to make sure they're always closed appropriately, like this:
using (WebResponse response = request.GetResponse())
using (Stream responseStream = response.GetResponseStream())
using (Stream outputStream = File.OpenWrite("map(" + i + ").png"))
{
responseStream.CopyTo(outputStream);
}
You can call WebClient.DownloadFile(url, localPath)
.
In .Net 4.0, you can simplify your current code by calling Stream.CopyTo
.
精彩评论