一、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. LeetCode 617. 合并二叉树(Merge Two Binary Trees)

    617. 合并二叉树 617. Merge Two Binary Trees 题目描述 给定两个二叉树,想象当你将它们中的一个覆盖到另一个上时,两个二叉树的一些节点便会重叠. 你需要将他们合并为一个新 ...

  2. LeetCode 242. 有效的字母异位词(Valid Anagram)

    242. 有效的字母异位词 LeetCode242. Valid Anagram 题目描述 给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的一个字母异位词. 示例 1: 输入: s ...

  3. java后台面试之计算机网络问题集锦

    1.http和https的区别 2.对称加密和非对称加密 3.三次握手与四次挥手的流程 4.为什么TCP需要三次握手?两次不可以吗?为什么 5.为什么TCP挥手需要四次?三次不行吗? 6.TCP协议如 ...

  4. Win10使用Xmanager6远程桌面连接CentOS7服务器

    服务器:CentOS 7.6 GNOME桌面环境(若最小化安装,默认是无桌面的,那么就要安装桌面,参考百度) 个人主机:Windows 10专业版,请安装Xmanager Power Suite 6( ...

  5. springboot使用neo4j

    springboot2.2使用neo4j第一次更新先放一些代码进来,下次加注释1.引入相应的包<dependency> <groupId>org.springframework ...

  6. Zuul【自定义Filter】

    实际业务中,如果要自定义filter过滤器,只需集成ZuulFIlter类即可,该类是个抽象类,它实现了IZuulFIlter接口,我们需要实现几个方法,如下示例: import static org ...

  7. php获取当前月的天数

    <?php //php获取当前月份的所有天数 $start_day = date('Ym01', time()); $end_day = date('Ymd', strtotime(" ...

  8. Oracle和SQL Server 用当前日期减去 '0001-01-01' 得出的天数不一致,相差2天,谁知道原因?

    Oracle和SQL Server 用当前日期减去 '0001-01-01' 得出的天数不一致,相差2天.求大佬科普

  9. UnknownError: session deleted because of page crash from tab crashed

    一.问题 在docker上跑Selenium+ChromeDriver+Chrome无头模式报错: UnknownError: unknown error: session deleted becau ...

  10. FFMPEG - ffplay源代码分析

    FFmpeg是一个开源,免费,跨平台的视频和音频流方案,它提供了一套完整的录制.转换以及流化音视频的解决方案.而ffplay是有ffmpeg官方提供的一个基于ffmpeg的简单播放器.学习ffplay ...