
正文
[C#]Stream.Write Extension Method
提示:扫一扫查出行【扫一扫了解最新限行尾号】
复制提示
在处理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,用以處理進度的顯示。
view source
print?
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,每當在處理時偵測到進度改變時會顯示出當前處理的進度比例。
view source
print?
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
|
}
|
運行結果如下:






