http://www.oseye.net/user/kevin/blog/86

概念

数据流(Stream)是对串行传输数据的一种抽象表示,是对输入/输出的一种抽象。数据有来源和目的地,衔接两者的就是串流对象。用比喻的方式来说或,数据就好比水,串流对象就好比水管,通过水管的衔接,水由一端流向另一端,如下图所示:

从应用程序的角度来说,如果将数据从来源取出,可以试用输入(读)串流,把数据储存在内存缓冲区;如果将数据写入目的地,可以使用输出(写)串流,把内存缓冲区的数据写入目的地:

当希望通过网络传输数据,或者对文件数据进行操作时,首先需要将数据转化为数据流。典型的数据流和某个外部数据源相关,数据源可以是文件、外部设备、内存、网络套接字等。根据数据源的不同,.能Net提供了多个从Stream类派生的子类,每个类代表一种具体的数据流类型,如何磁盘文件直接相关的文件流类FileStream,和套接字相关的网络流类NetworkStream,和内存相关的内存流类MemoryStream等。


流具有如下3种基本操作:

  • 写入:将数据从内存缓冲区传输到外部源;
  • 读取:将数据从外部源传输到内存缓冲区;
  • 查找:重新设置流的当前位置,以便随机读写。但并不是所有的流类型都支持查找,如网络流类没有当前位置的概念,就不支持查找。

Stream是虚拟类,它以及它的派生类都提供了Read和Write方法,可以支持在字节级别上对数据进行读写。Read方法从当前字节流读取字节放至内存缓冲区,Write方法把内存缓冲区的字节写入当前流中。

封装的其他流类

但仅支持字节级别的数据处理会给开发人员带来不便。将定应用程序需要将字符数据写入到流中,则需要先将字符数据转化为字节数组之后才能调用Write方法写入流。因此,除了Stream及其派生类的读写方法之外,.Net框架同样提供了其他多种支持流读写的类:

  • BinaryReader:从Streams读取编码的字符串和基元数据类型;
  • BinaryWriter:向Streams写入编码的字符串和基元数据类型;
  • StreamReader:通过使用Encoding将字符转换为字节,向Streams写入字符;
  • StreamWriter:通过使用Encoding进行字符和字节的转换,可直接从Streams中读取字符;

一、文件流 FileStream

FileStream流继承与Stream类,一个FileStream类的实例实际上代表一个文件流,使用FileStream类可以对文件系统上是文件进行读取、写入、打开和关闭操作。

创建FileStream实例

1、.Net提供多种获取FileStream对象的方法,其中构造函数就有10多种,我们看下典型的构造函数顺便讲解下参数含义:

  1. publicFileStream(string path,FileMode mode,FileAccess access);

参数说明:
path指明文件所在的路径信息;
mode是FileMode的枚举值,表示文件打开或创建的方式,含义如下:

  • CreateNew:指定操作系统应创建新文件,如果文件已经存在,则引发IOException;
  • Create:指定操作系统应创建新文件,如果文件已经存在,它将被覆盖;
  • Open:指定操作系统应打开现有文件,如果文件不存在,则引发FileNotFoundException;
  • OpenOrCreate:指定操作系统应打开文件,如果文件不存在,则创建新文件;
  • Truncate:指定操作系统应打开现有文件,文件一旦打开,就将截断为零字节大小;
  • Append:打开先有文件并把Position设置至文件尾,如果文件不存在将创建新文件。Append只能同FileAccess.Write一起使用;

access是FileAccess的枚举值,它控制对文件的访问权限,含义如下:

  • Read:打开文件用于只读;
  • Write:打开文件用于只写;
  • ReadWrite:打开文件,用于读写;

2、除了FileStream类本身提供的构造函数外,System.IO命名空间下的File和FileInfo类也提供了创建FileStream对象的方法。其中OpenRead方法返回只读文件流,OpenWrite方法返回只写文件流。如:

FileStream fs=File.OpenRead(@"c:\file.txt");

FileStream的读写方法:

public override intRead(
byte[] array,//内存缓冲区,储存从文件流中读取的数据
int offset,//array开始写入数据的下标值
int count //从文件流中读取的字节大小
); public override void Write(
byte[] array,//内存缓冲区,存储了要写入流的字节数据
int offset,// 从array的下标值开始取数据
int count //要写入的字节数
);

FileStream实例 

try
{
//写入
FileStream fileStream =newFileStream(@"d:\test.txt",FileMode.OpenOrCreate);
byte[] content =Encoding.UTF8.GetBytes("我爱我家");
fileStream.Write(content,, content.Length);
fileStream.Position=;//设置当前位置
content =Encoding.UTF8.GetBytes("我爱你家"); fileStream.Write(content,, content.Length);
fileStream.Close(); //读取
fileStream =newFileStream(@"d:\test.txt",FileMode.Open);
content =newbyte[fileStream.Length];
fileStream.Read(content,, content.Length);
Console.WriteLine(Encoding.UTF8.GetString(content));
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}

二、内存流 MemoryStream

和文件流布同,MemoryStream类表示的是保存在内存中的数据流,由内存流封装的数据可以在内存中直接访问。内存一般用于暂时缓存数据以降低应用程序对临时缓冲区和临时文件的需要。

既然字节数据也在内存中存储,为什么还要引入内存流的概念呢?这是因为内存流和字节数组虽然都位于程序缓冲区,但是具有不同特性。内存流相对于字节数组而言,具有流特有的特性,并且容量可自动增长,在数据加密以及对长度不定的数据进行缓存等场合,使用内存流比较方便。

创建MemoryStream实例

MemoryStream有多种构造函数,部分举例如下:

  • public MemoryStream();该构造函数初始分配的容量大小为0,随着数据的不断写入,其容量可以不断地自动扩展。
  • public MemoryStream(byte[] buffer);根据字节数组buffer初始化,实例的容量大小规定为字节数组的长度。
  • public MemoryStream(int capacity);容量固定为capacity。

MemoryStream实例

MemoryStream mem =newMemoryStream();
Console.WriteLine("初始分配的容量:"+mem.Capacity+" 初始使用量:"+mem.Length);
byte[] content =Encoding.UTF8.GetBytes("我爱我家");
mem.Write(content,, content.Length);
Console.WriteLine("初始分配的容量:"+ mem.Capacity+" 初始使用量:"+ mem.Length);

三、网络流NetWorkStream

网络流的意思是数据在网络的各个位置之间是以连续的字节形式传输的,NetWorkStream只能用于面向连接的套接字。

对于NetWorkStream流,写入操作是指从来源端内存缓冲区到网络上的数据传输;读取操作是从网络上到接收端内存缓冲区的数据传输。

一、StreamWriter和StreamReader

从上一篇博文可知文件流、内存流和网络流操作的都是字节,每次都要进行字节序列的转换,所以使用上比较麻烦。StreamWriter和StreamReader在对Stream底层进行了封装,可以直接操作字符数据。

StreamWriter类主要完成一种特定的编码从流中读取字符的功能,它的构造函数和常用方法如下:

  • StreamWriter(Stream stream),构造函数,StreamWriter不仅能对FileStream对象,而且能够对NetWorkStream、MemoryStream等继承了Stream类的流对象进行封装;
  • StreamWriter(string path),构造函数,如需要处理的是文件流,则可直接利用文件路径创建以UTF8编码的StreamWriter对象;
  • Write(string value),方法,向数据流写入数据;
  • WriteLine(string value),方法,向数据流写入数据,并追加一个换行符(Unix)或回车换行符(Windows);
  • Close(),方法,关闭流,释放资源;

StreamReader类主要以特定的编码向流中写入字符,它的构造函数和常用方法如下:

  • StreamReader(Stream stream),构造函数,利用流对象创建StreamReader对象;
  • StreamReader(string path),构造函数,如需要处理的是文件流,则可直接利用文件路径创建以UTF8编码的StreamReader对象;
  • string ReadLine(),方法,读取数据直到遇到换行符(Unix)或回车换行符(Windows);
  • string ReadToEnd(),方法,读取到文件尾的全部数据
  • int Peek(),方法,返回数据中下一个可用字符的编码值,如到达文件末尾则返回-1;
  • Close(),方法,关闭流,释放资源;

StreamWriter和StreamReader实例

try
{
//写入
StreamWriter sw =newStreamWriter(@"d:\abc.txt");
sw.WriteLine("我爱我家");
sw.Close(); //读取
StreamReader sr =newStreamReader(@"d:\abc.txt");
Console.WriteLine(sr.ReadToEnd());
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}

二、BinaryReader和BinaryWriter

为了操作图像、压缩文件等二进制流文件,System.IO还提供了BinaryReader类和BinaryWriter类,用于二进制模式的读写流。
BinaryReader的每个读方法都有一个对应的写方法,比如针对不同的数据结构,BinaryReader类提供了ReadByte、ReadBoolean、ReadInt、ReadInt16、ReadString等,与之对应的BinaryReader类则提供了多个重载的Write方法,分别对应上面的读方法,所以使用起来非常方便。例如,当Write方法传递的参数是Int32类型时,利用BinaryWriter的Write方法可用将Int32类型数据转化为长度为4的字节数组,并将字节流传递给一个Stream对象。

BinaryReader和BinaryWriter实例

byte[] sendData;
using (MemoryStream mem =newMemoryStream()){
BinaryWriter writer =newBinaryWriter(mem,Encoding.UTF8);
writer.Write(SocketTools.strConvertToHexByte(SocketTools.md5(packageHead.CarIdentifier,)));
writer.Write(packageHead.ProjectIdentifier);
writer.Write(packageHead.ModelIdentifier);
writer.Write(packageHead.ProtocolVersion);
writer.Write(SocketTools.reverseShort(packageHead.RequestSerial));
writer.Write(SocketTools.reverseInt32(packageHead.PacketTimestamp));
writer.Write(SocketTools.reverseShort(packageHead.FunctionNo));
writer.Write(SocketTools.reverseShort(packageHead.DataLength));
writer.Write(msg.ToCharArray());
sendData = mem.ToArray();
writer.Close();
}

(转载)NET流操作的更多相关文章

  1. Hadoop基础-通过IO流操作HDFS

    Hadoop基础-通过IO流操作HDFS 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.上传文件 /* @author :yinzhengjie Blog:http://www ...

  2. Scala进阶之路-I/O流操作之文件处理

    Scala进阶之路-I/O流操作之文件处理 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 说起Scala语言操作文件对象其实是很简单的,大部分代码和Java相同. 一.使用Scal ...

  3. Storm实时计算:流操作入门编程实践

    转自:http://shiyanjun.cn/archives/977.html Storm实时计算:流操作入门编程实践   Storm是一个分布式是实时计算系统,它设计了一种对流和计算的抽象,概念比 ...

  4. Java8中的流操作-基本使用&性能测试

    为获得更好的阅读体验,请访问原文:传送门 一.流(Stream)简介 流是 Java8 中 API 的新成员,它允许你以声明式的方式处理数据集合(通过查询语句来表达,而不是临时编写一个实现).这有点儿 ...

  5. Node学习笔记(一):stream流操作

    NodeJs中谈及较多的可能就是Stream模块了,先写一个简单的ajax回调 $.post("index.php",{data:'aaa',order:'ccc'},functi ...

  6. [WCF编程]10.操作:流操作

    一.流操作概述 在默认情况下,当客户端调用服务时,服务只有在接收到完整的消息后才会被调用,同样,客户端只有在包含了调用结果的返回消息被完整接受时,才会解除对它的阻塞. 对于数据量小的消息,这种交换模式 ...

  7. io流操作大全

    JAVA 中的IO流 一.流的概念        流(stream)的概念源于UNIX中管道(pipe)的概念.在UNIX中,管道是一条不间断的字节流,用来实现程序或进程间的通信,或读写外围设备.外部 ...

  8. Stream 流操作

     Stream 类 先看下面的图 Stream 是所有流的抽象基类(不能被实例化,需要使用他的派生类FileStream/MemoryStream/BufferedStream).流是字节序列的抽象概 ...

  9. delphi 基础之三 文件流操作

    文件流操作 Delphi操作流文件:什么是流?流,简单来说就是建立在面向对象基础上的一种抽象的处理数据的工具.在流中,定义了一些处理数据的基本操作,如读取数据,写入数据等,程序员是对流进行所有操作的, ...

随机推荐

  1. linux查看文件个数命令

    linux下查看当前目录下文件个数命令: 使用背景:有时想了解一个目录下具体有多少文件或者有多少文件夹. 1. 查看当前目录下文件个数 ls -l |grep "^-"|wc -l ...

  2. ###《Effective STL》--Chapter5

    点击查看Evernote原文. #@author: gr #@date: 2014-09-17 #@email: forgerui@gmail.com Chapter5 算法 Topic 30: 确保 ...

  3. angular2 select change 事件

    刚开始这是啥?(wrong!!!    change事件会在 选择option行为  之前执行prodDirId,是取不到选择后正确的id值的,取得是选择行为前prodDirId的值(有试过setTi ...

  4. 如何一行jquery代码写出tab标签页(链式操作)

    啦啦!今天又学了一招,js写几十行的tab标签页jquery写一行就行啦,用到了链式操作!以下是代码: <!DOCTYPE html> <html lang="en&quo ...

  5. JavaScript 学习笔记: 扩充类型的功能

    JavaScript 是允许给基本类型扩充功能的.例如,可以通过对Object.prototype增加方法,可以让该方法对所有的对象都可用. 这样的方式对函数,数组,字符串,数字,正则表达式和布尔值同 ...

  6. javascript学习笔记4

    1. 分析一下代码执行结果 分析为什么? var  a = 12;  b = 34; c = 56; ++a;    //a结果 13 a++;    //a结果 14 c = ++a + b;   ...

  7. nginx 常用的 URL 重写方法

    转自:http://www.jbxue.com/article/4727.html Nginx中一些常用的URL 重写方法介绍,有需要的朋友可以参考下.url重写应该不陌生,不管是SEO URL 伪静 ...

  8. shell中的重定向(2>&1)

    shell的输出可以分为标准输出和错误输出,2>&1中,2代表错误输出,1代表标准输出,&符号代表后面跟的是代号而不是文件. test.sh echo '我是标准输出' ls / ...

  9. 使用imp加载python模块

    import impimport sysfn_, path, desc = imp.find_module('mymodule', ['/data/module/'])print fn_,path,d ...

  10. Django视图函数

    一.视图函数 1. 视图函数的第一个参数一定是一个HTTPRequest类型的对象,这个对象是Django自动创建的,具体形参名通常用request.通过这个对象,可以调用请求的一些参数,比如requ ...