在处理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. discuz二次开发笔记(二)------跳转函数运用

    前几天在增加修改功能时,突然用到一个提示函数,有点不理解,看了他的由来后果断做下笔记,感觉这在以后的开发中肯定还是要用的上的.有些地方不是很理解,在以后慢慢纠正.查补. Htm页面中用的js跳转: $ ...

  2. php中的一些编程例子

    #一到一百不能被三整除的数 for($i=1;$i<=100;$i++){ if($i%3 != 0){ $arr[] = $i; }} var_dump($arr); #水仙花数for($i= ...

  3. centos 添加epel、remi仓库和ELRepo仓库

    centos使用yum安装软件非常方便,yum会自动安装软件的相关依赖.但是centos自带的源仓库,软件相对老旧并且不太全,所以我们可以添加第三方仓库,可以安装较新的软件版本. epel是fedor ...

  4. linux的NetworkManager服务

    在开启NetworkManager服务的情况下,在终端下敲“service network restart”命令: 正在关闭接口 eth0: 设备状态:3 (断开连接) [确定] 正在关闭接口 eth ...

  5. Python学习笔记2-Python神奇的语法和格式化输出

    先来看一个例子: class Fish: hungry=True def eat(self,food): if food is not None: self.hungry=False class Us ...

  6. AndroidUI 视图动画-旋转动画效果 (RotateAnimation)

    RotateAnimation,能实现Android的视图的旋转效果,废话不多说直接上代码. 新建一个Android 项目,在activity_main.xml中添加一个按钮,然后使用Relative ...

  7. linux内核源码阅读之facebook硬盘加速flashcache之六

    其实到目前为止,如果对读流程已经能轻松地看懂了,那么写流程不需要太多脑细胞.我觉得再写下去没有太大的必要了,后面想想为了保持flashcache完整性,还是写出来吧.接着到写流程: 1530stati ...

  8. Android编程之LayoutInflater的inflate方法具体解释

    LayoutInflater的inflate方法,在fragment的onCreateView方法中经经常使用到: public View onCreateView(LayoutInflater in ...

  9. android 基本控件使用

    http://tech.it168.com/a2012/0321/1327/000001327704.shtml Android_ListView_用代码控制ListView的位置 有三种方法 mli ...

  10. html系列教程--元素

    HTML 元素语法 HTML 元素以开始标签起始 HTML 元素以结束标签终止 元素的内容是开始标签与结束标签之间的内容 某些 HTML 元素具有空内容(empty content) 空元素在开始标签 ...