一、Stream类概述

在.NET Framework中,文件和流是有区别的。文件是存储在磁盘上的数据集,它具有名称和相应的路径。当打开一个文件并对其进行读/写时,该文件就称为流(stream)。但是,流不仅仅是指打开的磁盘文件,还可以是网络数据。.Net Framework允许在内存中创建流。此外,在控制台应用程序中,键盘输入和文本显示都是流。

属性

  • Length    当在派生类中重写时,获取流长度(以字节为单位)。
  • Position    当在派生类中重写时,获取或设置当前流中的位置。
  • ReadTimeout    获取或设置一个值(以毫秒为单位),该值确定流在超时前尝试读取多长时间。
  • WriteTimeout    获取或设置一个值(以毫秒为单位),该值确定流在超时前尝试写入多长时间。

方法

  • Seek(Int64, SeekOrigin)    当在派生类中重写时,设置当前流中的位置。
  • Read(Byte[], Int32, Int32)    当在派生类中重写时,从当前流读取字节序列,并将此流中的位置提升读取的字节数。
  • ReadByte()    从流中读取一个字节,并将流内的位置向前提升一个字节,或者如果已到达流结尾,则返回 -1。
  • Write(Byte[], Int32, Int32)    当在派生类中重写时,向当前流中写入字节序列,并将此流中的当前位置提升写入的字节数。
  • WriteByte(Byte)    将一个字节写入流内的当前位置,并将流内的位置向前提升一个字节。
  • CopyTo(Stream, Int32)    使用指定的缓冲区大小,从当前流中读取字节并将其写入到另一流中。
  • Close()    关闭当前流并释放与之关联的所有资源(如套接字和文件句柄)。 不直接调用此方法,而应确保流得以正确释放。
  • Flush()    当在派生类中重写时,将清除该流的所有缓冲区,并使得所有缓冲数据被写入到基础设备。

二、 操作流的类

1. Stream类

Stream类是所有流的抽象基类。

Stream类的主要属性有CanRead(是否支持读取)、CanSeek(是否支持查找)、CanTimeout(是否可以超时)、CanWrite(是否支持写入)、Length(流的长度)、Position(获取或设置当前流中的位置)、ReadTimeout(获取或设置读取操作的超时时间)、WriteTimeout(获取或设置写操作的超时时间),

Stream类的主要方法有BeginRead(开始异步读操作),BeginWrite(开始异步写操作)、Close(关闭当前流)、EndRead(结束异步读操作)、EndWrite(结束异步写操作)、Flush(清除流的所有缓冲区并把缓冲数据写入基础设备)、Read(读取字节序列)、ReadByte(读取一个字节)、Seek(设置查找位置)、Write(写入字节序列)、WriteByte(写入一个字节)。

2. FileStream、MemoryStream和BufferedStream,NetworkStream

  • 文件流类FileStream:以流的形式读、写、打开、关闭文件。另外,它还可以用来操作诸如:管道、标准输入/输出等其他与文件相关的操作系统句柄。
  • 内存流MemoryStream类:用来在内存中创建流,以暂时保持数据,因此有了它就无须在硬盘上创建临时文件。它将数据封装为无符号的字节序列,可以直接进行读、写、查找操作。
  • 缓冲流BufferedStream类:表示把流先添加到缓冲区,再进行数据的读/写操作。缓冲区是存储区中用来缓存数据的字节块。使用缓冲区可以减少访问数据时对操作系统的调用次数,增强系统的读/写功能。
  • 网络流NetworkStream类:为网络访问提供数据的基础流。

注意,FileStream类也有缓冲功能,在创建FileStream类的实例时,只需要指定缓冲区的大小即可。

三、文件流类 FileStream

文件流类FileStream公开了以文件为主的Stream,既支持同步读/写操作,也支持异步读/写操作。

FileStream类的特点是操作字节和字节数组。这种方式不适合操作用字符数据构成的文本文件,适合处理非文本文件。FileStream类提供了对文件的低级而复杂的操作,因此能够实现更多高级的功能。

1、读文件

Read,ReadByte()

//创建d:\file.txt的FileStream对象
FileStream fstream = new FileStream(@"d:\file.txt", FileMode.OpenOrCreate);
byte[] bData = new byte[fstream.Length];
//设置流当前位置为文件开始位置
fstream.Seek(0, SeekOrigin.Begin); //设置流当前位置为文件开始位置
fstream.Seek(0, SeekOrigin.Begin);
//将文件的内容存到字节数组中(缓存)
fstream.Read(bData, 0, bData.Length);
string result = Encoding.UTF8.GetString(bData);
Console.WriteLine(result);
if (fstream != null)
{
//清除此流的缓冲区,使得所有缓冲的数据都写入到文件中
fstream.Flush();
fstream.Close();
}

将字节数组转成字符串显示以外,字节数组还可以

//1、显示成图片
MemoryStream mstream = new MemoryStream(bData);
Image img = Image.FromStream(mstream);
//2、作为值存储到数据库
SqlCommand comm = new SqlCommand();
comm.Parameters.Add("images", SqlDbType.Image).Value = bData;
//3、写入文件
File.WriteAllBytes("c:\aa.txt", bData);
FileStream fstream = new FileStream("c:\aa.txt");
fstream.Write(bData, 0, bData.Length);

2、分块读文件

int bufferSize = 5;
//创建d:\file.txt的FileStream对象
FileStream fstream = new FileStream(@"d:\file.txt", FileMode.OpenOrCreate, FileAccess.Read, FileShare.Read, bufferSize, false);//false表示同步读
byte[] bData = new byte[bufferSize];
//设置流当前位置为文件开始位置
fstream.Seek(0, SeekOrigin.Begin);
int bytesRead;
do
{
//将文件的内容存到字节数组中(缓存)
bytesRead = fstream.Read(bData, 0, bData.Length);
string result = Encoding.UTF8.GetString(bData, 0, bytesRead);
Console.WriteLine(result);
} while (bytesRead > 0); if (fstream != null)
{
//清除此流的缓冲区,使得所有缓冲的数据都写入到文件中
fstream.Flush();
fstream.Close();
}

3、异步读文件

ManualResetEvent mEvent = new ManualResetEvent(false);
int bufferSize = 5;
byte[] bData = new byte[bufferSize];
FileStream fstream = new FileStream(@"d:\file.txt", FileMode.OpenOrCreate, FileAccess.Read, FileShare.Read, bufferSize, true);//false表示异步读
AsyncCallback callback = null;
callback = (IAsyncResult ar) =>
{
int bytesRead = fstream.EndRead(ar);
Console.WriteLine(Encoding.UTF8.GetString(bData, 0, bytesRead));
if (bytesRead > 0)
{
fstream.BeginRead(bData, 0, bufferSize, callback, null);//继续读
}
else
{
fstream.Close();
mEvent.Set();//读取完毕,发送信号
}
}; IAsyncResult async = fstream.BeginRead(bData, 0, bufferSize, callback, null);
mEvent.WaitOne(5000, false);
Console.WriteLine("读取完成");

4、IAsyncResult 接口

  • AsyncState    获取一个用户定义的对象,该对象限定或包含有关异步操作的信息。
  • AsyncWaitHandle    获取用于等待异步操作完成的 WaitHandle。
  • CompletedSynchronously    获取一个值,该值指示异步操作是否同步完成。
  • IsCompleted    获取一个值,该值指示异步操作是否已完成。

4、写文件

Write,WriteByte(Byte)

//创建d:\file.txt的FileStream对象
FileStream fstream = new FileStream(@"d:\file.txt", FileMode.OpenOrCreate);
byte[] bData = Encoding.UTF8.GetBytes("test filestream");
//设置流当前位置为文件开始位置
fstream.Seek(0, SeekOrigin.Begin);
//将字节数组中的内容写入文件
fstream.Write(bData, 0, bData.Length);
if (fstream != null)
{
//清除此流的缓冲区,使得所有缓冲的数据都写入到文件中
fstream.Flush();
fstream.Close();
}

四、以二进制格式序列化对象BinaryFormatter

1、SoapFormatter(用于HTTP中)和BinaryFormatter(用于TCP中)类实现了IFormatter接口 (由继承IRemotingFormatter,支持远程过程调用 (Rpc))

  • Deserialize(Stream)    反序列化所提供流中的数据并重新组成对象图形。
  • Serialize(Stream, Object)    将对象或具有给定根的对象图形序列化为所提供的流。

XML序列化见:https://www.cnblogs.com/springsnow/p/9469399.html

2、举例:

[Serializable]
public class Product //实体类
{
public long Id;
[NonSerialized]//标识不序列化此成员Name
public string Name;
public Product(long Id, string Name)
{
this.Id = Id;
this.Name = Name;
}
} static void Main()
{
//序列化(对象保存到文件)
List<Product> Products = new List<Product> {
new Product(1,"a"),new Product(2,"b")
}; FileStream fs = new FileStream("DataFile.dat", FileMode.Create);
IFormatter formatter = new BinaryFormatter();
formatter.Serialize(fs, Products);
fs.Close(); //反序列化(文件内容转成对象)
FileStream fs1 = new FileStream("DataFile.dat", FileMode.Open);
BinaryFormatter formatter1 = new BinaryFormatter();
List<Product> addresses = (List<Product>)formatter1.Deserialize(fs1);
fs1.Close();
foreach (Product de in addresses)
{
Console.WriteLine("{0} lives at {1}.", de.Id, de.Name);
}
}

五、内存流MemoryStream

内存流相对字节数组而言,具有流特有的特性,并且容量可自动增长。

在数据加密以及对长度不定的数据进行缓存等场合,使用内存流比较方便。下面的代码示例演示如何读取和写入将内存用作后备存储的数据。

int count;
UnicodeEncoding uniEncoding = new UnicodeEncoding(); // Create the data to write to the stream.
byte[] firstString = uniEncoding.GetBytes("Invalid file path characters are: ");
byte[] secondString = uniEncoding.GetBytes(Path.GetInvalidPathChars()); using (MemoryStream memStream = new MemoryStream(100))
{
// Write the first string to the stream.
memStream.Write(firstString, 0, firstString.Length); // Write the second string to the stream, byte by byte.
count = 0;
while (count < secondString.Length)
{
memStream.WriteByte(secondString[count++]);
} // Write the stream properties to the console.
Console.WriteLine("Capacity = {0}, Length = {1}, Position = {2}\n", memStream.Capacity.ToString(), memStream.Length.ToString(), memStream.Position.ToString()); // Set the position to the beginning of the stream.
memStream.Seek(0, SeekOrigin.Begin); // Read the first 20 bytes from the stream.
byte[] byteArray = new byte[memStream.Length];
count = memStream.Read(byteArray, 0, 20); // Read the remaining bytes, byte by byte.
while (count < memStream.Length)
{
byteArray[count++] = Convert.ToByte(memStream.ReadByte());
} // Decode the byte array into a char array and write it to the console.
char[] charArray = new char[uniEncoding.GetCharCount(byteArray, 0, count)];
uniEncoding.GetDecoder().GetChars(byteArray, 0, count, charArray, 0);
Console.WriteLine(charArray);
}

ToArray()与GetBuffer()的区别:

byte[] byteArray = memStream.ToArray();将流中的数据复制到一个byte[]中,速度比GetBuffer()稍慢,但不会将无用的空数据放入buffer中。

byte[] byteArray = memStream.GetBuffer();把流中的Buffer的引用传递出来,速度较快,Buffer的大小有流的Capacity决定的,但传无用的空数据。

文件读写(三)利用FileStream类操作字节数组byte[]、BinaryFormatter、内存流MemoryStream的更多相关文章

  1. c#中字节数组byte[]、图片image、流stream,字符串string、内存流MemoryStream、文件file,之间的转换

    字节数组byte[]与图片image之间的转化 字节数组转换成图片 public static Image byte2img(byte[] buffer) { MemoryStream ms = ne ...

  2. C#中字节数组(byte[])和字符串相互转换

    转换过程主要使用到System.Text.Encoding命名空间下的类 1. 字符串转换成字节数组byte[]: string str = "This is test string&quo ...

  3. C#-----字节数组(byte[])和字符串相互转换

       Encoding类  表示字符编码 1.字符串转换成字节数组byte[] using System; using System.Collections.Generic; using System ...

  4. 字节数组byte[]和整型,浮点型数据的转换——Java代码

    近期在写C++ socket和java socket之间的通信程序,涉及到整数浮点数的传输.须要从字节数组还原数据,查了一些资料.总结例如以下 1.       整数和浮点数的机器表示 在机器内部.不 ...

  5. [.Net,C#]三类资源:流对象Stream,字节数组byte[],图片Image

    三类资源:流对象Stream,字节数组byte[],图片Image 关系:Stream<=>byte[],byte[]<=>Image Stream 与Image相互转化的媒介 ...

  6. Java基础知识强化之IO流笔记27:FileInputStream读取数据一次一个字节数组byte[ ]

    1. FileInputStream读取数据一次一个字节数组byte[ ]  使用FileInputStream一次读取一个字节数组: int read(byte[]  b) 返回值:返回值其实是实际 ...

  7. C#中字节数组byte[]和字符串string类型的相互转换

    C#中字节数组byte[]和字符串string类型的相互转换: string转byte[]: byte[] byteArray = System.Text.Encoding.Default.GetBy ...

  8. Python之IO编程——文件读写、StringIO/BytesIO、操作文件和目录、序列化

    IO编程 IO在计算机中指Input/Output,也就是输入和输出.由于程序和运行时数据是在内存中驻留,由CPU这个超快的计算核心来执行,涉及到数据交换的地方,通常是磁盘.网络等,就需要IO接口.从 ...

  9. 快速入门Python中文件读写IO是如何来操作外部数据的?

    读写文件是最常见的IO操作.Python内置了读写文件的函数,用法和C是兼容的. 读写文件前,我们先必须了解一下,在磁盘上读写文件的功能都是由操作系统提供的,现代操作系统不允许普通的程序直接操作磁盘, ...

随机推荐

  1. redis服务操作

    端口启动服务./redis/redis-2.8.19/src/redis-server /redis/conf/r6100.conf./redis/redis-2.8.19/src/redis-ser ...

  2. linux服务器安装svn并上传项目

    一.安装svn (1)安装svn服务器: yum install subversion (2)查看版本(随自己意愿): svnserve --version 二.创建svn仓库并配置 (1)创建svn ...

  3. (三)shiro的认证

    文章目录 认证思路 自定义用于登录检验的Realm的思路 代码实现 后记 认证思路 调用 SecurityUtils.getSubject() 方法,获取当前的 Subject 对象 : 调用 Sub ...

  4. 湖北校园网PC端拨号算法逆向

    湖北校园网PC端拨号算法逆向 前言 上一文 PPPoE中间人拦截以及校园网突破漫谈我们谈到使用 PPPoE 拦截来获取真实的账号密码. 在这个的基础上,我对我们湖北的客户端进行了逆向,得到了拨号加密算 ...

  5. SPA项目首页导航+左侧菜单

    Mock.js是个啥 前后端分离之后,前端迫切需要一种机制,不再需要依赖后端接口开发,而今天的主角mockjs就可以做到这一点 Mock.js是一个模拟数据的生成器,用来帮助前端调试开发.进行前后端的 ...

  6. C++ 相关问题记录

    目录 编译链接 使用初始化和使用赋值时,调用的函数不同:使用 auto_ptr() 时可能会出现编译错误 宏定义不受命名空间的约束 Switch-case 中不能定义变量 技巧/注意项 多层继承中基类 ...

  7. Tomcat Lifecycle

    org.apache.catalina.Lifecycle 接口统一管理生命周期,所有生命周期组件都要实现Lifecycle接口. 该接口定义了13个String类型的常量,用于LifecycleEv ...

  8. SQL case when 遇到null值

    case  when f.FPH is  NULL then a.HSJE else f.KPHSJE  end    yes case f.FPH  when   NULL then a.HSJE ...

  9. 我对xss以及sql的理解

    我对xss以及sql的理解 本文作者:情殇(查看作者所有博文) 作者邮箱:3135117931@qq.com 发布时间: Fri, 12 Jul 2019 19:16:00 +0800 Xss和sql ...

  10. 时间都去哪儿了?开源一个统计iPhone上App运行时间和打开次数的小工具【iOS8已失效】

    如今,大家每天都有大量时间花在手机上,但是,大家有没有想过自己的时间都花在哪些App上了呢?相信很多人都有这样的需求,不过iOS系统本身并不能显示每个App的运行时间和次数,因此,本人写了这样一个小工 ...