我的编程空间,编程开发者的网络收藏夹
学习永远不晚

C#使用文件流FileStream和内存流MemoryStream操作底层字节数组byte[]

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

C#使用文件流FileStream和内存流MemoryStream操作底层字节数组byte[]

一、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();

到此这篇关于C#使用文件流FileStream和内存流MemoryStream操作底层字节数组byte[]的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持编程网。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

C#使用文件流FileStream和内存流MemoryStream操作底层字节数组byte[]

下载Word文档到电脑,方便收藏和打印~

下载Word文档

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录