在处理Stream型态时常会使用到Stream.Write这个方法,每次都会有种疑问就是,大多数的处理都是要将Buffer整个写入,為何偏偏每次都要将索引带0,长度带為Buffer的大小呢?另外在处理Stream时,若要显示其处理进度,是否能有更為简单的方法?这边将我為了解决这些问题所写的扩充方法整裡如下:

using System;
02 using System.Reflection;
03 using System.ComponentModel;
04 using System.Linq;
05 using System.IO;
06  
07 public static class StreamExtension
08 {
09     public static void Write(this Stream targetStream, byte[] buffer)
10     {
11         if (!targetStream.CanWrite)
12             throw new ArgumentException("targetStream", "Unwritable stream");
13  
14         targetStream.Write(buffer, 0, buffer.Length);
15     }
16  
17     public static void Write(this Stream targetStream, Stream sourceStream)
18     {
19         if (!targetStream.CanWrite)
20             throw new ArgumentException("targetStream", "Unwritable stream");
21  
22         if (sourceStream == null)
23             throw new ArgumentNullException("sourceStream");
24  
25         if (!sourceStream.CanRead)
26             throw new ArgumentException("sourceStream", "Unreadable stream");
27  
28         targetStream.Write(sourceStream, 1024, null);
29     }
30  
31     public static void Write(this Stream targetStream, Stream sourceStream, int bufferSize, Action<object, System.ComponentModel.ProgressChangedEventArgs> progressChangedCallBack)
32     {
33         if (sourceStream == null)
34             throw new ArgumentNullException("sourceStream");
35  
36         if (!sourceStream.CanRead)
37             throw new ArgumentException("sourceStream", "Unreadable stream");
38  
39         if (!targetStream.CanWrite)
40             throw new ArgumentException("targetStream", "Unwritable stream");
41  
42         if (bufferSize < 1024)
43             throw new ArgumentOutOfRangeException("bufferSize", "Must bigger than 1024");
44  
45         byte[] buffer = new byte[bufferSize];
46  
47         int offset = 0;
48         int readByteCount = 0;
49         int percent = 0;
50  
51         while ((readByteCount = sourceStream.Read(buffer, 0, bufferSize)) > 0)
52         {
53             targetStream.Write(buffer, 0, readByteCount);
54  
55             if (progressChangedCallBack != null)
56             {
57                 offset += readByteCount;
58  
59                 var currentPercent = (int)(((double)offset) / sourceStream.Length * 100);
60                 if (currentPercent == percent)
61                     continue;
62  
63                 percent = currentPercent;
64                 progressChangedCallBack(targetStream, new System.ComponentModel.ProgressChangedEventArgs(percent, null));
65             }
66         }
67     }
68 }

使用上Write方法會多三個多載版本,一個是將buffer整個寫入、一個是將stream的內容整個讀出並寫入、一個則是用來寫入整個stream內容,並可帶入處理的Buffer大小,與處理進度回報的Callback,用以處理進度的顯示。

1 targetStream.Write(buffer);
2 targetStream.Write(sourceStream);
3 targetStream.Write(sourceStream, 1024, (sender, e) => { Console.WriteLine(e.ProgressPercentage.ToString ()); });

這邊針對進度處理的擴充方法示範個較為詳細的範例,這邊我會讀取C槽下的test.data檔案,檔案大小為5MB多,開啟後將其寫入c槽下的test_copy.data。處理的buffer大小為1024,每當在處理時偵測到進度改變時會顯示出當前處理的進度比例。

01 using System;
02 using System.Collections.Generic;
03 using System.Linq;
04 using System.Text;
05 using System.IO;
06  
07 namespace ConsoleApplication11
08 {
09     class Program
10     {
11         static void Main(string[] args)
12         {           
13                 using (FileStream targetStream = File .Create (@"c:\test_copy.dat"))
14                 {
15                     using (FileStream sourceStream= File.Open (@"c:\test.dat", FileMode.Open))
16                     {
17                         targetStream.Write(sourceStream, 1024, (sender, e) => { Console.WriteLine(e.ProgressPercentage.ToString()); });
18                     }
19                 }
20         }
21     }
22 }

運行結果如下:

[C#]Stream.Write Extension Method的更多相关文章

  1. [C#] Extension Method 扩展方法

    当我们引用第三方的DLL.或者Visual Studio自己的库的时候,或许会发现这样的一个情况,如果这个类型有一个XX的方法就好了.这时候我们可以用到扩展方法,是我们的代码更加灵活和高效. 这里我举 ...

  2. 动态linq表达式新方法,Dynamic LINQ Extension Method

    Remember those old posts on Dynamic LINQ? You are probably aware that Microsoft has made its impleme ...

  3. Extension Method[下篇]

    四.Extension Method的本质 通过上面一节的介绍,我们知道了在C#中如何去定义一个Extension Method:它是定义在一个Static class中的.第一个Parameter标 ...

  4. Extension Method[上篇]

    在C#3.0中,引入了一些列新的特性,比如: Implicitly typed local variable, Extension method,Lambda expression, Object i ...

  5. C# Note21: 扩展方法(Extension Method)及其应用

    前言 今天在开会时提到的一个概念,入职3个多月多注重在项目中使用C#的编程知识,一直没有很认真地过一遍C#的全部语法,当我们新人被问及是否了解Extension Method时,一时之间竟不能很通俗准 ...

  6. [译文]c#扩展方法(Extension Method In C#)

    原文链接: https://www.codeproject.com/Tips/709310/Extension-Method-In-Csharp 介绍 扩展方法是C# 3.0引入的新特性.扩展方法使你 ...

  7. C#编译问题'System.Collections.Generic.IEnumerable' does not contain a definition for 'Where' and no extension method 'Where' accepting a first argument

    &apos;System.Collections.Generic.IEnumerable<string>&apos; does not contain a definiti ...

  8. Swift protocol extension method is called instead of method implemented in subclass

    Swift protocol extension method is called instead of method implemented in subclass protocol MyProto ...

  9. Extension method for type

    扩展其实真的很简单 msdn是这样规定扩展方法的:"扩展方法被定义为静态方法,但它们是通过实例方法语法进行调用的. 它们的第一个参数指定该方法作用于哪个类型,并且该参数以 this 修饰符为 ...

随机推荐

  1. javascript的调试

    1. 关于javascript的调试,最好将浏览器的脚本通知打开. 2. 最好设置为每次访问页面时检查.

  2. 当tomcat有两个链接数据库的应用同时运行可能冲突

    -Xms512M   -Xmx1024M -XX:MaxPermSize=256M

  3. IPTV小窗口播放视频 页面焦点无法移动的解决方法

    在IPTV高清页面中,小窗口播放视频时,在某些机顶盒上(如高清中兴.高清大亚4904)会出现焦点无法移动现象,即按键无响应.被这个bug困扰了很久,虽然我知道解决方法,但只知其然,不知其所以然.今天做 ...

  4. bootstrap 简易模版

    <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content ...

  5. Canvas、Paint、的简单使用及辅助类(Path、Shader、简介)

    1.Canvas类 作用:1.绘制各种图形.图片.字等.2.提供各种方法进行坐标变换(rotate.scale.skew.translate) 获取Canvas:一般是子类继承View并重写onDra ...

  6. PHP面试题之算法解析

    面试中经常被问到会什么算法,这里整合一些常见的算法及它们的实现原理.下面的例子都是经过测试可用的,如果有什么问题请告知!! 本人小白,如果有更好的实现方式,敬请赐教,感激不尽!!!! 冒泡排序,快速排 ...

  7. Java 中使用Jackson反序列化

    Build.gradle: compile group: 'org.codehaus.jackson', name: 'jackson-mapper-lgpl', version: '1.9.13' ...

  8. Android05-UI02布局,自定义控件,ListView

    1.布局 布局的内部除了放置控件外,也可以放置布局,通过多层布局的嵌套,我们就能够完成一些 比较复杂的界面实现 ¨四种基本布局 LinearLayout RelativeLayout FrameLay ...

  9. php set env

    SYSTEM WARNING: 'date_default_timezone_get(): It is not safe to rely on the system's timezone settin ...

  10. 公司需求知识自学- Hashtable简单应用

    定义表 Hashtable tblNames = new Hashtable(); 添加key,value键值对 tblNames.Add("A","a"); ...