在处理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. ASP.NET DataList绑定数据并实现分页

    显示当前页码Label属性 值ID NowPageNumberLabtext    1 ×××××××××××××××××××××显示总页码Label属性 值ID BackPageNumberLabt ...

  2. JAVA 8 新特性和改进

    Java 8的所有新特性及改进包括(JEP全称为JDK Enhancement Proposal,JDK改进建议): 语言改进: JEP 126:Lambda表达式 & 虚拟扩展方法 JEP ...

  3. 写给初学者css优先级问题

    首先需要搞清楚几个基本概念 1.内嵌样式: 写在元素标签内的例如:<div style="background-color:red"> </div> 2.内 ...

  4. TensorFlow 深度学习笔记 Logistic Classification

    Logistic Classification Github工程地址:https://github.com/ahangchen/GDLnotes 欢迎star,有问题可以到Issue区讨论 官方教程地 ...

  5. SQL Server 查看指定表上的索引

    解决方案: sys.indexs; ---------------------------------------------------------------------------------- ...

  6. aix运维

    AIX操作系统中有很多程序,为了进行程序版本控制,每一个程序集都有自己的版本号.版本号是由小数点分隔的四位数字,例如5.3.0.9其含义是:操作系统版本号(version).发行版本号(release ...

  7. mysql数据库学习(二)--表操作

    一.表操作 以下内容都是自己学习的时候看过的一些知识,作为笔记记录一下吧,大部分都是所看文章的内容. 1.创建表 前面的基础篇笔记是相当于搭建了一个方便管理的文件夹树根,下面要学习的是一些关于表的知识 ...

  8. AngularJs(三) deployd 服务的使用

    使用服务建立数据 在AngularJS(二)中,我搭建好了deployd服务,现在启动服务,创建正在的数据(开始是使用模拟数据),使用cmd命令 一.开启Mongodb数据. 贴图: 二:测试是否正常 ...

  9. html标签总结。

    接触了一段时间的html和css,发现了其中的乐趣.在写代码时一定要仔细,很有可能一个细微的错误便会导致页面的错误 总结了一下html标签. <html></html> 创建一 ...

  10. JAVA 从GC日志分析堆内存 第七节

    JAVA 从GC日志分析堆内存 第七节   在上一章中,我们只设置了整个堆的内存大小.但是我们知道,堆又分为了新生代,年老代.他们之间的内存怎么分配呢?新生代又分为Eden和Survivor,他们的比 ...