.net System.IO之Stream的使用详解
本篇文章是对.Net中System.IO之Stream的使用进行了详细的分析介绍,需要的朋友参考下
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方法从流中读取字节,如下示例注释:
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就是实实在在的异步操作了。
如下示例代码和注释:
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对象,然后向内存流中写入一个字节数组
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/newsouls/p/3146325.html
.net System.IO之Stream的使用详解相关推荐
- (116)System Verilog类合成(类包含关系)详解
(116)System Verilog类合成(类包含关系)详解 1.1 目录 1)目录 2)FPGA简介 3)System Verilog简介 4)System Verilog类合成(类包含关系)详解 ...
- java函数式编程归约reduce概念原理 stream reduce方法详解 reduce三个参数的reduce方法如何使用
java函数式编程归约reduce概念原理 stream reduce方法详解 reduce三个参数的reduce方法如何使用
- IO流输入输出流入门详解
IO流输入输出流入门详解 1.Java中以流的形式处理数据 2.流是一种有序的数据序列,分为输入输出流 3.Java是面向对象的程序设计语言,每个数据都是一个对象 4.Java中的输入输出功能来自ja ...
- .Net 文件流 System.IO之Stream
转自 :http://www.cnblogs.com/yukaizhao/archive/2011/07/28/stream.html Stream在msdn的定义:提供字节序列的一般性视图(prov ...
- java.IO字节流和字符流详解
IO流的分类 在学习字节流和字符流之前因该先学习IO流的分类,效果会更好 有多种分类方式: 一种方式是按照流的方向进行分类: 以内存作为参照物, 往内存中去,叫做输入(Input).或者叫做读(Rea ...
- linux 监控命令iostat,Linux下 IO实时监控iostat命令详解
Linux系统中的iostat是I/O statistics(输入/输出统计)的缩写,iostat工具将对系统的磁盘操作活动进行监视.它的特点是汇报磁盘活动统计情况,同时也会汇报出CPU使用情况.同v ...
- java8 四大函数式接口 和 用于数据处理的 stream流 使用详解
文章目录 Stream 使用示例 四大函数式接口 Function 功能型接口 Consumer 消费型接口 Supplier 提供型接口 Predicate 断言型接口 常用 api stream, ...
- Java Stream流(详解)
一.Stream流引入 Lambda表达式,基于Lambda所带来的函数式编程,又引入了一个全新的Stream概念,用于解决集合类库既有的鼻端.(Lambda表达式详解在上篇博客内容) ...
- IO测试工具之fio详解
目前主流的第三方IO测试工具有fio.iometer和Orion,这三种工具各有千秋. fio在Linux系统下使用比较方便,iometer在window系统下使用比较方便,Orion是oracle的 ...
- Linux IO复用区别与epoll详解
转载:http://blog.csdn.net/hacker00011000/article/details/52160590 一.select.poll.epoll之间的区别总结[整理] sele ...
最新文章
- 手把手教你如何新建scrapy爬虫框架的第一个项目(下)
- Java通过链表实现队列
- POI对EXCEL的操作【重点:如何设置CELL格式为文本格式】
- cookies默认过期时间_「图」Chrome Canary新版已启动“增强版cookies控制”预览测试...
- 具有GlassFish和一致性的高性能JPA –第1部分
- 1894. 找到需要补充粉笔的学生编号
- 【Hive】性能调优 - map-side JOIN
- jQuery Mobile中按钮button的data-*选项
- 阻止电脑自动安装软件_一套连招彻底阻止流氓软件静默安装
- 国外除了Google还有什么搜索引擎?
- 毕向东_JavaScript视频教程_javascript编程
- 【Android病毒分析报告】- 手机支付毒王“银行悍匪”的前世今生
- 泛微oa系统服务器怎么填写,泛微协同办公平台Ecology8安装部署手册(105页)-原创力文档...
- 爱了爱了!从草根到百万年薪程序员的十年风雨之路,小白也能看明白
- STM32CubeMX | | 使用小熊派串口驱动峰汇ETH-01以太网模块上传数据到OneNet
- 研究生的压力应对与心理健康 测试题答案
- 玩转Redis-HyperLogLog统计微博日活月活
- Frida在windows上的玩法
- Axure自定义Echarts交互图
- 配置 Spring Batch 批处理失败重试机制