2010-12-12 99 views
1

使用C#,我很惊讶它似乎从流中保存二进制信息有多复杂。我正尝试使用WebRequest类下载PNG数据文件,但只是将生成的Stream传输到文件,而不会破坏它比我想象的更详细。首先,仅仅使用StreamReader和StreamWriter是不好的,因为ReadToEnd()函数返回一个字符串,这有效地使PNG文件的大小加倍(可能是由于UTF转换)保存流中的二进制数据

所以我的问题是,我真的有编写所有这些代码,还是有一个更干净的方式来做到这一点?

  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 (count != 0); 
      swBytes.Close(); 
+2

你永远不应该对待任意字节流作为字符串,但。因为他们不是。 – Joey 2010-12-12 14:21:44

回答

4

使用StreamReader/StreamWriter肯定是一个错误,是的 - 因为这是试图加载文件作为文本,它不是。

选项:

  • 使用WebClient.DownloadFile作为SLaks建议
  • 在.NET 4中,使用Stream.CopyTo(Stream)以几乎相同的方式将数据复制,你现在看到
  • 否则,你写自己的实用方法来做复制,那么你只需要做一次;你甚至可以这样写一个扩展方法,当你升级到.NET 4你可以摆脱实用方法和使用,这意味着内置一个没有改变调用代码:

    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); 
         } 
        } 
    } 
    

请注意,你应该使用以网络响应,响应流和输出流using报表,以确保他们总是在适当的关闭,像这样:

using (WebResponse response = request.GetResponse()) 
using (Stream responseStream = response.GetResponseStream()) 
using (Stream outputStream = File.OpenWrite("map(" + i + ").png")) 
{ 
    responseStream.CopyTo(outputStream); 
} 
+1

Skiiilz :)谢谢 – 2010-12-12 14:38:47