博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
.Net 文件流 System.IO之Stream
阅读量:6983 次
发布时间:2019-06-27

本文共 6532 字,大约阅读时间需要 21 分钟。

转自 :http://www.cnblogs.com/yukaizhao/archive/2011/07/28/stream.html

 

Stream在msdn的定义:提供字节序列的一般性视图(provides a generic view of a sequence of bytes)。这个解释太抽象了,不容易理解;从stream的字面意思“河,水流”更容易理解些,stream是一个抽象类,它定义了类似“水流”的事物的一些统一行为,包括这个“水流”是否可以抽水出来(读取流内容);是否可以往这个“水流”中注水(向流中写入内容);以及这个“水流”有多长;如何关闭“水流”,如何向“水流”中注水,如何从“水流”中抽水等“水流”共有的行为。

常用的Stream的子类有:

1) MemoryStream 存储在内存中的字节流

2) FileStream  存储在文件系统的字节流

3) NetworkStream 通过网络设备读写的字节流

4) BufferedStream 为其他流提供缓冲的流

Stream提供了读写流的方法是以字节的形式从流中读取内容。而我们经常会用到从字节流中读取文本或者写入文本,微软提供了StreamReader和StreamWriter类帮我们实现在流上读写字符串的功能。

下面看下如何操作Stream,即如何从流中读取字节序列,如何向流中写字节

1. 使用Stream.Read方法从流中读取字节,如下示例注释:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
using 
System;
using 
System.Collections.Generic;
using 
System.Linq;
using 
System.Text;
using 
System.IO;
 
namespace 
UseStream
{
    
class 
Program
    
{
        
//示例如何从流中读取字节流
        
static 
void 
Main(
string
[] args)
        
{
            
var bytes =
new 
byte
[] {(
byte
)1,(
byte
)2,(
byte
)3,(
byte
)4,(
byte
)5,(
byte
)6,(
byte
)7,(
byte
)8};
            
using 
(var memStream =
new 
MemoryStream(bytes))
            
{
                
int 
offset = 0;
                
int 
readOnce = 4;
                 
                
do
                
{
                    
byte
[] byteTemp =
new 
byte
[readOnce];
                    
// 使用Read方法从流中读取字节
                    
//第一个参数byte[]存储从流中读出的内容
                    
//第二个参数为存储到byte[]数组的开始索引,
                    
//第三个int参数为一次最多读取的字节数
                    
//返回值是此次读取到的字节数,此值小于等于第三个参数
                    
int 
readCn = memStream.Read(byteTemp, 0, readOnce);
                    
for 
(
int 
i = 0; i < readCn; i++)
                    
{
                        
Console.WriteLine(byteTemp[i].ToString());
                    
}
                     
                    
offset += readCn;
 
                    
//当实际读取到的字节数小于设定的读取数时表示到流的末尾了
                    
if 
(readCn < readOnce)
break
;
                
}
while 
(
true
);
            
}
 
            
Console.Read();
        
}
    
}
}

 

2. 使用Stream.BeginRead方法读取FileStream的流内容

注意:BeginRead在一些流中的实现和Read完全相同,比如MemoryStream;而在FileStream和NetwordStream中BeginRead就是实实在在的异步操作了。

如下示例代码和注释:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
using 
System;
using 
System.Collections.Generic;
using 
System.Linq;
using 
System.Text;
using 
System.IO;
using 
System.Threading;
 
namespace 
UseBeginRead
{
    
class 
Program
    
{
        
//定义异步读取状态类
        
class 
AsyncState
        
{
            
public 
FileStream FS {
get
;
set
; }
 
            
public 
byte
[] Buffer {
get
;
set
; }
 
            
public 
ManualResetEvent EvtHandle {
get
;
set
; }
        
}
 
        
static  
int 
bufferSize = 512;
 
        
static 
void 
Main(
string
[] args)
        
{
            
string 
filePath =
"d:\\test.txt"
;
            
//以只读方式打开文件流
            
using 
(var fileStream =
new 
FileStream(filePath, FileMode.Open, FileAccess.Read))
            
{
                
var buffer =
new 
byte
[bufferSize];
 
                
//构造BeginRead需要传递的状态
                
var asyncState =
new 
AsyncState { FS = fileStream, Buffer = buffer ,EvtHandle =
new 
ManualResetEvent(
false
)};
 
                
//异步读取
                
IAsyncResult asyncResult = fileStream.BeginRead(buffer, 0, bufferSize,
new 
AsyncCallback(AsyncReadCallback), asyncState);
 
                
//阻塞当前线程直到读取完毕发出信号
                
asyncState.EvtHandle.WaitOne();
                
Console.WriteLine();
                
Console.WriteLine(
"read complete"
);
                
Console.Read();
            
}
        
}
 
        
//异步读取回调处理方法
        
public 
static 
void 
AsyncReadCallback(IAsyncResult asyncResult)
        
{
            
var asyncState = (AsyncState)asyncResult.AsyncState;
            
int 
readCn = asyncState.FS.EndRead(asyncResult);
            
//判断是否读到内容
            
if 
(readCn > 0)
            
{
                
byte
[] buffer;
                
if 
(readCn == bufferSize) buffer = asyncState.Buffer;
                
else
                
{
                    
buffer =
new 
byte
[readCn];
                    
Array.Copy(asyncState.Buffer, 0, buffer, 0, readCn);
                
}
 
                
//输出读取内容值
                
string 
readContent = Encoding.UTF8.GetString(buffer);
                 
                
Console.Write(readContent);
            
}
 
            
if 
(readCn < bufferSize)
            
{
                
asyncState.EvtHandle.Set();
            
}
            
else 
{
                
Array.Clear(asyncState.Buffer, 0, bufferSize);
                
//再次执行异步读取操作
                
asyncState.FS.BeginRead(asyncState.Buffer, 0, bufferSize,
new 
AsyncCallback(AsyncReadCallback), asyncState);
            
}
        
}
    
}
}

 

3. 使用Stream.Write方法向流中写字节数组

在使用Write方法时,需要先使用Stream的CanWrite方法判断流是否可写,如下示例定义了一个MemoryStream对象,然后向内存流中写入一个字节数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
using 
System;
using 
System.Collections.Generic;
using 
System.Linq;
using 
System.Text;
using 
System.IO;
 
namespace 
UseStreamWrite
{
    
class 
Program
    
{
        
static 
void 
Main(
string
[] args)
        
{
            
using 
(var ms =
new 
MemoryStream())
            
{
                
int 
count = 20;
                
var buffer =
new 
byte
[count];
                
for 
(
int 
i = 0; i < count; i++)
                
{
                    
buffer[i] = (
byte
)i;
                
}
 
                
//将流当前位置设置到流的起点
                
ms.Seek(0, SeekOrigin.Begin);
 
                
Console.WriteLine(
"ms position is " 
+ ms.Position);
 
                
//注意在调用Stream的Write方法之前要用CanWrite判断Stream是否可写
                
if 
(ms.CanWrite)
                
{
                    
ms.Write(buffer, 0, count);
                
}
 
                
//正确写入的话,流的位置会移动到写入开始位置加上写入的字节数
                
Console.WriteLine(
"ms position is " 
+ ms.Position);
 
            
}
 
            
Console.Read();
        
}
    
}

4. 使用Stream.BeginWrite方法异步写;异步写可以提高程序性能,这是因为磁盘或者网络IO的速度远小于cpu的速度,异步写可以减少cpu的等待时间。

如下使用FileStream异步写文件的操作示例

using 
System;
using 
System.Collections.Generic;
using 
System.Linq;
using 
System.Text;
using 
System.IO;
using 
System.Threading;
 
namespace 
UseStreamBeginWrite
{
    
class 
Program
    
{
        
/// <summary>
        
/// 异步回调需要的参数封装类
        
/// </summary>
        
class 
AsyncState {
            
public 
int 
WriteCountOnce {
get
;
set
; }
 
            
public 
int 
Offset {
get
;
set
; }
 
            
public 
byte
[] Buffer {
get
;
set
; }
 
            
public 
ManualResetEvent WaitHandle {
get
;
set
; }
 
            
public 
FileStream FS {
get
;
set
; }
        
}
 
        
static 
void 
Main(
string
[] args)
        
{
            
//准备一个1K的字节数组
            
byte
[] toWriteBytes =
new 
byte
[1 << 10];
            
for 
(
int 
i = 0; i < toWriteBytes.Length; i++)
            
{
                
toWriteBytes[i] = (
byte
)(i %
byte
.MaxValue);
            
}
 
            
string 
filePath =
"d:\\test.txt"
;
            
//FileStream实例
            
using 
(var fileStream =
new 
FileStream(filePath, FileMode.Create, FileAccess.ReadWrite, FileShare.Read))
            
{
                
int 
offset = 0;
                
//每次写入32字节
                
int 
writeCountOnce = 1 << 5;
 
                
//构造回调函数需要的状态
                
AsyncState state =
new 
AsyncState{
                    
WriteCountOnce = writeCountOnce,
                    
Offset = offset,
                    
Buffer = toWriteBytes,
                    
WaitHandle =
new 
ManualResetEvent(
false
),
                    
FS = fileStream
                
};
 
                
//做异步写操作
                
fileStream.BeginWrite(toWriteBytes, offset, writeCountOnce, WriteCallback, state);
 
                
//等待写完毕或者出错发出的继续信号
                
state.WaitHandle.WaitOne();
            
}
 
            
Console.WriteLine(
"Done"
);
 
            
Console.Read();
        
}
 
        
/// <summary>
        
/// 异步写的回调函数
        
/// </summary>
        
/// <param name="asyncResult">写状态</param>
        
static 
void 
WriteCallback(IAsyncResult asyncResult)
        
{
            
AsyncState state = (AsyncState)asyncResult.AsyncState;
             
            
try
            
{
                
state.FS.EndWrite(asyncResult);
            
}
            
catch 
(Exception ex)
            
{
                
Console.WriteLine(
"EndWrite Error:" 
+ ex.Message);
                
state.WaitHandle.Set();
                
return
;
            
}
 
            
Console.WriteLine(
"write to " 
+ state.FS.Position);
            
//判断是否写完,未写完继续异步写
            
if 
(state.Offset + state.WriteCountOnce < state.Buffer.Length)
            
{
                
state.Offset += state.WriteCountOnce;
                
Console.WriteLine(
"call BeginWrite again"
);
                
state.FS.BeginWrite(state.Buffer, state.Offset, state.WriteCountOnce, WriteCallback, state);
            
}
            
else 
{
                
//写完发出完成信号
                
state.WaitHandle.Set();
            
}
        
}
    
}
}

转载于:https://www.cnblogs.com/IT-Bear/archive/2013/01/18/2865848.html

你可能感兴趣的文章
IT十八掌掌第二天课程总结
查看>>
职业SNS天际网:透视“屌丝文化” 解析当今职场
查看>>
Leetcode 29. Divide Two Integers
查看>>
Kubernetes 1.5集成heapster
查看>>
清华赵骥主任与CIO石海军研讨互联网信息化
查看>>
tnsname.ora文件解析
查看>>
论文:论项目的计划和监控
查看>>
linux启动引导过程 grub和mbr
查看>>
lnmp环境安装
查看>>
Codeforces Round #438 868A/B/C
查看>>
每天一个linux命令(4):mkdir命令
查看>>
课后作业4之个人总结
查看>>
php常用的系统函数大全
查看>>
Jade To Pug过程中的一个小问题
查看>>
在ubuntu中搜索文件或文件夹的方法
查看>>
ioc——实现原理
查看>>
腾讯hr面
查看>>
iOS开发之SceneKit框架--SCNGeometry.h
查看>>
对事件委托绑定click的事件的解绑
查看>>
localstorage和sessionstorage上手使用记录
查看>>