C#使用文件流FileStream和内存流MemoryStream操作底层字节数组byte[]
作者:springsnow 发布时间:2023-09-04 00:30:55
一、Stream类概述
在.NET Framework中,文件和流是有区别的。
文件是存储在磁盘上的数据集,它具有名称和相应的路径。当打开一个文件并对其进行读/写时,该文件就称为流(stream)。
但是,流不仅仅是指打开的磁盘文件,还可以是网络数据。.Net Framework允许在内存中创建流。此外,在控制台应用程序中,键盘输入和文本显示都是流。
1. Stream类
Stream类是所有流的抽象基类。
Stream类的主要属性有CanRead、CanWrite(是否支持读取写入)、CanSeek(是否支持查找)、CanTimeout(是否可以超时)、Length(流的长度)、Position(获取或设置当前流中的位置)、ReadTimeout/WriteTimeout(获取或设置读、写操作的超时时间)
Stream类的主要方法有BeginRead/EndRead(开始结束异步读操作),BeginWrite/EndWrite(开始结束异步写操作)、Read(读取字节序列)、ReadByte(读取一个字节)、Seek(设置查找位置)、Write(写入字节序列)、WriteByte(写入一个字节)、 Flush(清除流的所有缓冲区并把缓冲数据写入基础设备)、Close(关闭当前流)。
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.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("读取完成");
备注: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();
}
三、内存流MemoryStream类
内存流相对字节数组而言,具有流特有的特性,并且容量可自动增长。
在数据加密以及对长度不定的数据进行缓存等场合,使用内存流比较方便。
下面的代码示例演示如何读取和写入将内存用作后备存储的数据。
int count;
UnicodeEncoding uniEncoding = new UnicodeEncoding();
//创建要写入流的数据
byte[] firstString = uniEncoding.GetBytes("Invalid file path characters are: ");
byte[] secondString = uniEncoding.GetBytes(Path.GetInvalidPathChars());
using (MemoryStream memStream = new MemoryStream(100))
{
// 将第一个字符串写入流.
memStream.Write(firstString, 0, firstString.Length);
// 将第二个字符串按字节写入流.
count = 0;
while (count < secondString.Length)
{
memStream.WriteByte(secondString[count++]);
}
// 将流属性写入控制台.
Console.WriteLine("Capacity = {0}, Length = {1}, Position = {2}\n", memStream.Capacity.ToString(), memStream.Length.ToString(), memStream.Position.ToString());
// 将位置设置为流的开始.
memStream.Seek(0, SeekOrigin.Begin);
// 从流中读取前20个字节.
byte[] byteArray = new byte[memStream.Length];
count = memStream.Read(byteArray, 0, 20);
// 一个字节一个字节地读取剩下的字节.
while (count < memStream.Length)
{
byteArray[count++] = Convert.ToByte(memStream.ReadByte());
}
// 将字节数组解码为char数组并将其写入控制台.
char[] charArray = new char[uniEncoding.GetCharCount(byteArray, 0, count)];
uniEncoding.GetDecoder().GetChars(byteArray, 0, count, charArray, 0);
Console.WriteLine(charArray);
}
ToArray()与GetBuffer()的区别:
//将流中的数据复制到一个byte[]中,速度比GetBuffer()稍慢,但不会将无用的空数据放入buffer中。
byte[] byteArray = memStream.ToArray();
//把流中的Buffer的引用传递出来,速度较快,Buffer的大小有流的Capacity决定的,但会传无用的空数据。
byte[] byteArray = memStream.GetBuffer();
来源:https://www.cnblogs.com/springsnow/p/9428715.html


猜你喜欢
- Java平台的垃圾收集机制显著提高了开发者的效率,但是一个实现糟糕的垃圾收集器可能过多地消耗应用程序的资源。在Java虚拟机性能优化系列的第
- TCPTCP协议是面向连接、保证高可靠性(数据无丢失、数据无失序、数据无错误、数据无重复到达)传输层协议。TCP通过三次握手建立连接,通讯完
- SpringMVC文件上传中要解决的问题一、中文文件名编码问题通过过滤器解决二、文件位置存储问题放在当前项目下,作为静态资源,这样可以通过U
- 本文实例讲述了Java基于Swing实现的打猎射击游戏代码。分享给大家供大家参考。具体实现代码如下:package Game;import
- 一、场景描述仪器数据文件的格式包含Pdf、Word、Excel等多种,不同种格式的文件其数据的采集方式不同,因此定义仪器数据采集接口,并定义
- JWT简介Json Web Token(JWT):JSON网络令牌,是为了在网络应用环境间传递声明而制定的一种基于JSON的开放标准((RF
- 第一种方法这种方法需要配置 hibernate.cfg.xml 的属性 hibernate.hbm2ddl.auto,该属性值的具体说明如下
- 前言我们在学习Windows应用程序开发中,经常会用到消息对话框给用户或者管理员一些的消息提示,它们都是基于对MessageBox类的消息对
- 安卓开发网络请求可谓是安卓开发的灵魂,如果你不会网络请求,那么你开发的应用软件就是一具没有灵魂的枯骨。在安卓开发中进行网络请求和java中的
- zuul动态路由网关服务是流量的唯一入口。不能随便停服务。所以动态路由就显得尤为必要。数据库动态路由基于事件刷新机制热修改zuul的路由属性
- 本文实例为大家分享了Android Studio实现简单计算器功能的具体代码,供大家参考,具体内容如下程序步骤:(1)在布局文件定义一些计算
- 访问Controller返回400BadRequest问题SpringMVC使用自定义类型接收参数时, form提交会返回400 Bad R
- Java中避免NullPointerException的方法总结在字符串常量上调用equals// good"string lit
- 本文实例为大家分享了Unity实现3D循环滚动效果展示的具体代码,供大家参考,具体内容如下然后通过SetDepthAndPosition这个
- 网上的教程大都是手动通过protoc编译, 比较难用给当前工程添加"Google.Protobuf"和"Grp
- 方法一public static boolean isTablet(Context context) {
- 先给大家展示下效果图:不知道大家对效果图感觉怎么样,个人觉还不错,感兴趣的朋友可以参考下实现代码哦。public class ToggleB
- 目前的应用市场上,使用毛玻璃效果的APP随处可见,比如用过微信语音聊天的人可以发现,语音聊天页面就使用了高斯模糊效果。先看下效果图:&nbs
- http请求绕过Filter的实现实例场景:两个web服务器,A当做服务端,B为客户端,B通过Hessian远程访问A。A上加了sessio
- c#中通过反射可以方便的动态加载dll程序集,但是如果你需要对dll进行更新,却发现.net类库没有提供卸载dll程序集的方法。在.net