在处理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. python---连接MySQL第一页

    前言:python如果想要连接到MySQL要安装上相关的驱动才下:好在驱动程序在mysql的官网可以下载的到. 以下是我自己保存的一个conetos7版本 http://yunpan.cn/cLACS ...

  2. eclipse 改包名

    转载自: http://www.2cto.com/kf/201304/206747.html 1.在项目上右键,选择android tools->rename application packa ...

  3. struts2的对象工厂(ObjectFactory)

    ObjectFactory,是xwork中很重要的一个类,是产生action的地方.单独使用xwork的时候,action都是这个类创建的.struts2包装了ObjectFactory,自成了一个S ...

  4. 实现拦截API的钩子(Hook)

    道理不多讲,简单说就是将系统API的跳转地址,替换为我们自己写的API的地址,所以要求我们自定义的API函数要和被拦截的API有相同的参数.在用完后,记得恢复. 因为要挂全局的钩子,所以Hook的部分 ...

  5. WinForm 窗体与窗体相互嵌套

    只要将要被潜逃的的窗体的TopLeve设置为Flase即可像普通的控件一样,被添加到另外一个窗体中,TopLeve:是否为顶级窗口,下面来看代码: public partial class TTFor ...

  6. DB_Links创建际删除

    创建 create database link gadata0008 connect to gadata0008 identified by "gold" using 'ORA11 ...

  7. java中表示二进制、八进制、十进制、十六进制,double、float、整型

    java里不能这样表示二进制,只能是   8,10,16进制  8:         前置   0  10:      不需前置 16:      前置   0x   或者   0X double:2 ...

  8. C语言中为什么不能把char**赋给const char**

    这是我在知乎回答的一个问题. 这个问题是C中的一个深坑,首先说结论: char ** 和 const char ** 是两个不相容(incompatible)的类型,能够理解为不能直接赋值 在C11的 ...

  9. C# 学习笔记 C#基础

    今天第一天开通博客.恰好在学习C#,所以就准备把学到的知识要点记录下来. 基础类型 类型定义了值得蓝图.值是一个被变量或者常量所指定的存储位置,变量是指可以被改变的,而常量则相反,其值不可以便改变, ...

  10. 执行SQL存储脚本

    using System.Data.SqlClient; static void Main(string[] args) { string connString = @"Data Sourc ...