开发者

Preserving binary data in streams

开发者 https://www.devze.com 2023-01-30 08:25 出处:网络
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 t

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消