【.NET Core】.NET中的流(Stream)

【.NET Core】.NET中的流(Stream)

文章目录

  • 【.NET Core】.NET中的流(Stream)
    • 一、流(Stream)
      • 1.1 FileStream类
      • 1.2 IsolatedStorageFileStream类
      • 1.3 MemoryStream类
      • 1.4 BufferedStream类
      • 1.5 NetworkStream类
        • NetworkStream使用步骤
        • NetworkStream示例
      • 1.6 pipeStream类
      • 1.7 CryptoStream类
        • CrytoStream的加密方法
        • CrytoStream的解密方法

一、流(Stream)

C#中文件和流I/O(输入/输出)是指在存储媒介中传入或传出数据。在.NET中,System.IO命名空间包含允许以异步方式和同步方式对数据流和文件进行读取和写入操作的类型。这些命名空间还包含对文件执行压缩和解压缩的类型,以及通过管道和串端口启用通信的类型。

抽象基类Steam支持读取和写入字节。所有表示流的类都继承基类Stream类。Stream类及其派生类提供数据源和存储库的常见视图,使程序员不必了解操作系统和基础设备的具体细节。
在这里插入图片描述

流(Stream)System.IO.Stream是一个抽象类,提供了将字节,提供了将字节(读,写等)传输到源的标准方法。就像包装器类一样传输字节。需要从特定源读取/写入字节的类必须实现Stream类。

根据Stream类图,以提供从特定源读取/写入字节的功能:

1.1 FileStream类

用于对文件进行读取和写入操作。

1.2 IsolatedStorageFileStream类

用于对独立存储中的文件进行读取或写入操作。IsolatedStroageFileStreaml是由FileStream扩展来。在使用完类型后,直接或间接释放类型。若要直接释放,请使用 try/cath块中调用其Dispose方法。若要间接释放类型,使用using

IsolatedStorageFile isoFile =IsolatedStorageFile.GetStore(IsolatedStorageScope.User |
                             IsolatedStorageScope.Assembly |IsolatedStorageScope.Domain,
                             null,null);
IsolatedStorageFileStream isoStream =
                new IsolatedStorageFileStream("substituteUsername",
                System.IO.FileMode.Open,
                System.IO.FileAccess.Read,
                System.IO.FileShare.Read);
try
{

      SafeFileHandle aFileHandle = isoStream.SafeFileHandle;
      Console.WriteLine("A pointer to a file handle has been obtained. "
                    + aFileHandle.ToString() + " "
                    + aFileHandle.GetHashCode());
}
catch (Exception e)
{
      Console.WriteLine("Expected exception");
      Console.WriteLine(e);
}

1.3 MemoryStream类

用于作为后备存储对内存进行读取和写入操作。MemoryStream是内存流,为系统内存提供读写操作,由于MemoryStream是通过无符号字节数组组成,可以说MenoryStream的性能比较出色,所以它担当起了一些其他进行数据交换时的中间工作,同时可降低应用程序中对临时缓冲区和临时文件的需要,其实MemoryStream的重要性不亚FileStream,很多场合我们必须使用它来提高性能。

/// <summary>
/// 数据类对象转成字节流
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
/// MemoryStream: 创建其支持存储区为内存的流。
///IFormatter : 提供将序列化对象格式化的功能。
public static byte[] ObjectToBytes(object obj)
{
   using (MemoryStream ms = new MemoryStream())
   {
       //以二进制格式将对象或整个连接对象图形序列化和反序列化。
       IFormatter formatter = new BinaryFormatter();
       //把字符串以二进制放进memStream中
       formatter.Serialize(ms, obj);
       //返回从其创建此流的无符号字节数组。 是会返回所有分配的字节,不管用没用到。
       //返回无符号字节数组 ,无符号字节数组 其实就是byte(0~255),有符号字节sbyte(-128~127)
       return ms.GetBuffer();
   }
}
 
/// <summary>
/// 字节流转成数据类对象
/// </summary>
/// <param name="bytes"></param>
/// <returns></returns>
public static object BytesToObject(byte[] bytes)
{
   using (MemoryStream ms = new MemoryStream(bytes))
   { 
      //以二进制格式将对象或整个连接对象图形序列化和反序列化。
      IFormatter formatter = new BinaryFormatter();
      //把字符串以二进制放进memStream中
      return formatter.Deserialize(ms);
    }
}

1.4 BufferedStream类

BufferedStream常用于对其他流的一个封装,它必须和其他流结合一起使用。MemoryStream将所有的内容都放入内存中,而BufferedStream不是。BufferedStream在基础流吸入内存中能够提高读取与写入速度。但是缓冲区设置的大小对性能也有影响,默认值是4096字节,并能够根据需要自动增长,并且很多属性都与基础流一致,缓冲数据能够减少对操作系统的调用次数,缓冲数据主要存储在缓冲区中,缓冲区是内存中的字节块。BufferedStream类提供从基础数据源或存储库读取字节以及将字节写入基础数据源或存储库的实现,在不需要缓冲区时可以防止缓冲区降级输入和输出速度。

缓冲类型下,会在后台自动下载定长的内容,读的时候是从缓冲区中拿东西。这种模式最大的特点是半阻塞式,大部分情况下能大幅度提高处理速度。

在程序逻辑速度大大慢于IO速度时,此方法效率明显。最好是在大文件的情况下,分块读,分块写。

示例:

private static void Buf(string oPath, string copyPath)
{
     Stream s1, s2;
     BufferedStream bs1, bs2;
     byte[] b = new byte[1024];
     int i;
     //分别以读、写方式打开两个文件
     s1 = File.OpenRead(oPath);
     s2 = File.OpenWrite(copyPath);
     //使用缓冲流
     bs1 = new BufferedStream(s1);
     bs2 = new BufferedStream(s2);
     i = bs1.Read(b,0,1024);
     //从文件1中读取,写入到文件2中
     while (i > 0)
     {
          bs2.Write(b,0,i);
          i = bs1.Read(b,0,1024);
     }
     bs2.Flush();
     s1.Close();
     bs2.Close();
 }

1.5 NetworkStream类

NetworkStream类主要是提供用于网络访问的基础数据流,它主要是网络数据传输的载体,并提供同步,异步方法来访问网络数据流。虽然NetworkStream类有构造函数,但在实际情况中更多是通过TcpClient实例的GetStream方法来初始化NetworkStream实例。

NetworkStream使用步骤
  1. 在tcp连接中,Networkstream可以重复读取,重复写入,不用关掉连接。
  2. 关掉NetworkStream会自动关闭掉Tcp连接。
  3. NetworkStream不需要使用Flush方法,数据会自动发送。
  4. NetworkStream.read会阻塞线程直到有新的数据过来,所以,发送端不释放,接收端不能接收到数据。接收前先判断 DataAvailable 没有数据的不进行Read就能实时收到数据了。
  5. 如果发送端发送快,接收端接收慢,会造成数据堆叠,即接收端一次可能接收到发送端多次发送的数据流,可以在接收端返回确认接收完成后,再让发送端发送新数据。
NetworkStream示例
if(stream.DataAvailable)
{
    int receiveByteCount=0;//当前已接收数据量
    var headerByte = new byte[8];
    await stream.ReadAsync(headerByte,0,8);//数据前8位为真实文件长度
    long pictureByteLength = BitConverter.ToInt64(headerByte,0);//实际文件大小
    var buffer = new byte[1024];
    System.IO.MemoryStream ms = new System.IO.MemoryStream();
    int tempCount =0;
    do
    {
        tempCount = await stream.ReadAsync(buffer,0,buffer.Length);
        await ms.WriteAsync(buffer,0,tempCount);
        receiveByteCount+=tempCount;
    }while(recevieByteCount<pictureByteLength);//直到整个文件接收完成
}

1.6 pipeStream类

管道(pipeStream)是一种特殊的流,它可以用于在不同的线程之间传送数据。一个线程将数据输出到管道中,另一个线程从管道中读取需要的数据,实现不同线程之间的通信而无需通过临时文件。管道通信可以达到解耦的目的,产生数据的线程不需要直接调用处理数据的方法并等待返回结果,只需要将数据放入管道,接着继续执行自己的任务;而处理数据的线程直接从管道中拿出数据进行处理,不需要进行轮询来获取数据。
pipeStream使用步骤

  1. 创建 Pipe:创建一个缓冲区,用于读取和写入数据。
  2. 写入数据:使用 PipelineWriter 将数据写入缓冲区。
  3. 读取数据并处理:使用 PipelineReader 读取缓冲区中的数据,并进行处理。

pipeStream示例

public static async Task Main(string[] args)
{
     var data = new byte[] { 1, 2, 3, 4, 5 };
     // 创建缓冲区
     var pipe = new Pipe();
     // 写入数据到缓冲区
     await pipe.Writer.WriteAsync(data);
     // 读取数据并处理
     while (true)
     {
          var result = await pipe.Reader.ReadAsync();
          var buffer = result.Buffer;
          try
          {
              if (buffer.IsEmpty && result.IsCompleted)
              {
                  break;
              }
              // 处理数据
              foreach (var segment in buffer)
              {
                  Console.WriteLine(segment.Span[0]);
              }
            }
            finally
            {
                // 将已处理的数据从缓冲区中删除
                pipe.Reader.AdvanceTo(buffer.End);
             }
      }
}

1.7 CryptoStream类

公共语言运行时使用面向流的设计进行加密。 此设计的核心是CryptoStream。 任何加密对象实现CryptoStream可以链接在一起实现的任何对象Stream,因此,一个对象的流式处理的输出可以将其填充到另一个对象的输入。 中间结果 (从第一个对象的输出) 不需要进行单独存储。
应始终显式关闭你CryptoStream对象完成后使用它通过调用Clear方法。 执行此操作刷新基础流并使所有剩余的数据块由处理CryptoStream对象。 但是,如果在调用之前,会发生异常Close方法,CryptoStream对象可能不会关闭。 若要确保Close始终调用方法,将置于调用Clear方法内的finally块try / catch语句。

CrytoStream的加密方法
public static string ToEncrypt(string encryptKey, string str)
{
        byte[] byte_key = Encoding.Unicode.GetBytes(encryptKey);    //将密钥字符串转换为字节序列
        byte[] byte_data = Encoding.Unicode.GetBytes(str);          //将字符串转换为字节序列     
        using var des = DES.Create();                               //创建加密流对象
        using var memory_stream = new MemoryStream();               //创建内存流对象
        using var crypto_stream = new CryptoStream(memory_stream, des.
            CreateEncryptor(byte_key, byte_key), CryptoStreamMode.Write); //创建加密流对象
        crypto_stream.Write(byte_data, 0, byte_data.Length);        //向加密流中写入字节序列
        crypto_stream.FlushFinalBlock();                            //将数据压入基础流
        crypto_stream.Close();                                      //关闭加密流
        memory_stream.Close();                                      //关闭内存流
        return Convert.ToBase64String(memory_stream.ToArray());     //从内存流中获取并返回加密后的字符串
}
CrytoStream的解密方法
public static string ToDecrypt(string encryptKey, string str)
{
    byte[] byte_key = Encoding.Unicode.GetBytes(encryptKey); //将密钥字符串转换为字节序列
    byte[] byte_data = Convert.FromBase64String(str); //将加密后的字符串转换为字节序列
    using var des = DES.Create();//创建加密流对象
    using var memory_stream = new MemoryStream(byte_data);//创建内存流对象并写入数据
    using var crypto_stream = new CryptoStream(memory_stream, des.
    CreateDecryptor(byte_key, byte_key), CryptoStreamMode.Read);  //创建加密流对象
    byte[] bt_temp = new byte[200];//创建字节序列对象
    MemoryStream memory_stream_temp = new();//创建内存流对象
    int i = 0;//创建记数器
    while ((i = crypto_stream.Read(bt_temp, 0, bt_temp.Length)) > 0)  //使用while循环得到解密数据
    {
        memory_stream_temp.Write(bt_temp, 0, i);//将解密后的数据放入内存流
    }
    crypto_stream.Close(); //关闭加密流
    memory_stream.Close(); //关闭内存流
    return Encoding.Unicode.GetString(memory_stream_temp.ToArray());    //方法返回解密后的字符串
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/427143.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

STM32 (2)

1.stm32编程模型 将C语言程序烧录到芯片中会存储在单片机的flsah存储器中&#xff0c;给芯片上电后&#xff0c;Flash中的程序会逐条进入到CPU中去执行&#xff0c;进而CPU去控制各种模块&#xff08;即外设&#xff09;去实现各种功能。 2.寄存器和寄存器编程 CPU通过控制其…

公司电脑文件防泄密软件——| 中科数安

公司电脑文件防泄密软件是一种专门设计用于保护企业敏感信息和数据安全的软件。这些软件通过采用各种技术手段&#xff0c;如数据加密、访问控制、行为监控等&#xff0c;来防止公司的机密文件、客户资料、财务数据等被非法获取、复制或传播。 www.weaem.com 以下是公司电脑文件…

选项 打光 试题总结

试题1 被测物体100100mm&#xff0c;精度要求被测物体 &#xff0c;精度要求0.1mm&#xff0c;相机距被测物体在200&#xff5e;320mm之间&#xff0c;要求选择合适的相机和镜头&#xff1f; 分析如下&#xff1a; 通常我们用的相机靶面是4:3 的所以我们要用短边来计算视场&am…

Vue导出json数据到Excel表格

一、安装依赖 npm install file-saver --save npm install xlsx --save npm install script-loader --save-dev二、下载两个所需要的js文件Blob.js和 Export2Excel.js。 这里下载&#xff1a;下载地址 三、src目录下新建vendor文件夹&#xff0c;将Blob.js和 Export2Excel.j…

STM32学习和实践笔记(1): 装好了的keil μVision 5

2019年3月在淘宝上买了这块STM32的开发板&#xff0c;学了一段时间后就丢下了&#xff0c;今天重新捡起来&#xff0c;决定好好学习、天天向上。 对照教程&#xff0c;今天先把keil5装上了。 装的过程有以下几点值得记录下&#xff1a; 1&#xff09;用注册机时&#xff0c;…

x86中的TSS与任务切换

前言 今天在学习《深入理解Linux内核》的时候&#xff0c;发现出现了一个新的名词TSS&#xff08;Task-State Segment&#xff09;&#xff0c;这还是我第一次了解到原来x86提供了硬件级别的任务切换功能&#xff0c;之前以为任务切换都是操作系统实现的来着&#xff0c;这里也…

计算机电源的功率不足150W的几种主要原因?

180 至 250 伏 180-250伏 一般计算机电源的工作电压范围为 180 至 250 伏。 电脑电源是安装在电脑内部的电脑部件&#xff0c;负责将普通市电电源转换成电脑可以使用的电压。 电脑电源是一个开关电路&#xff0c;将普通交流电转换为直流电&#xff0c;然后通过斩波控制电压&a…

JavaScript 中的类型转换机制(详细讲解)

文章目录 一、概述二、显示转换Number()parseInt()String()Boolean() 三、隐式转换自动转换为布尔值自动转换成字符串自动转换成数值 一、概述 前面我们讲到&#xff0c;JS中有六种简单数据类型&#xff1a;undefined、null、boolean、string、number、symbol&#xff0c;以及…

你知道为什么输电线路除冰采用的是直流电而不是交流电呢?

2月22日以来&#xff0c;受新一轮寒潮影响&#xff0c;四川地区气温骤降&#xff0c;多地出现了零摄氏度以下的低温和冰冻天气&#xff0c;泥巴山、蓑衣岭等微气象区域20条500千伏线路出现不同程度覆冰&#xff0c;其中500千伏石雅四回线路覆冰最为严重&#xff0c;导线和铁塔上…

程序员在面试过程中需要重点关注的问题

在金三银四这个关键的求职季节&#xff0c;程序员面试的成功与否往往决定了他们能否获得心仪的工作机会。在这篇文章中&#xff0c;我将详细介绍程序员在面试过程中需要重点关注的问题&#xff0c;并提供一些实用的建议和技巧。 一、了解自己和职位要求 在面试之前&…

在线绘图利器:支持在线使用的电脑画图软件推荐!

计算机绘图软件是现代设计师和创作者必不可少的工具之一。伴随着技术的不断发展&#xff0c;越来越多的在线计算机绘图软件应运而生&#xff0c;为用户提供了更加便捷、高效的创作方法。对初学者而言&#xff0c;选择一款易于使用、功能强大的计算机绘图软件至关重要。本文将介…

39. 【Linux教程】修改文件所属关系

上一节介绍了如何修改文件的读、写、执行权限&#xff0c;包括属主用户权限、所属用户组权限、其他用户组用户权限&#xff0c;本小节介绍如何修改文件的所属关系&#xff0c;所属关系又包括文件的属主和所属组。 1.chown 命令 若想要修改文件的属主&#xff0c;可以使用 chow…

便携式启动电源的市场前景和商业机会

便携式启动电源是一种便携式电子设备&#xff0c;主要用于为飞机、火炮、汽车、船只等大型机械提供紧急启动电源。它通常由一个可充电的电池和一个充电器组成&#xff0c;可以方便地随身携带。 便携式启动电源的工作原理是通过将电池的电能转换为机械能&#xff0c;从而驱动汽…

Leetcoder Day38| 动态规划part05 背包问题

1049.最后一块石头的重量II 有一堆石头&#xff0c;每块石头的重量都是正整数。 每一回合&#xff0c;从中选出任意两块石头&#xff0c;然后将它们一起粉碎。假设石头的重量分别为 x 和 y&#xff0c;且 x < y。那么粉碎的可能结果如下&#xff1a; 如果 x y&#xff0c;那…

云端技术驾驭DAY15——ClusterIP服务、Ingress服务、Dashboard插件、k8s角色的认证与授权

往期回顾&#xff1a; 云端技术驾驭DAY01——云计算底层技术奥秘、云服务器磁盘技术、虚拟化管理、公有云概述 云端技术驾驭DAY02——华为云管理、云主机管理、跳板机配置、制作私有镜像模板 云端技术驾驭DAY03——云主机网站部署、web集群部署、Elasticsearch安装 云端技术驾驭…

Java中继承的作用及解析

在 Java 中&#xff0c;继承是一种非常重要的面向对象编程特性。它的主要作用包括以下几个方面&#xff1a; 代码复用&#xff1a;通过继承&#xff0c;子类可以复用父类的代码&#xff0c;包括属性和方法。这样可以避免重复编写相同的代码&#xff0c;提高代码的复用性和可维护…

keycloak-鉴权springboot

一、环境描述 keycloak鉴权springboot的方式&#xff0c;此处简单介绍&#xff0c;springboot官方也提供了demo https://github.com/keycloak/keycloak-quickstarts/tree/latest/spring/rest-authz-resource-server 以及文档说明 Securing Applications and Services Guide…

2024年智能驾驶年度策略:自动驾驶开始由创造型行业转向工程型行业

感知模块技术路径已趋于收敛&#xff0c;自动驾驶从创造型行业迈向工程型行业。在特斯拉的引领下&#xff0c;国内主机厂2022年以来纷纷跟随特斯拉相继提出“重感知、轻地图”技术方案&#xff0c;全球自动驾驶行业感知模块技术路径从百花齐放开始走向收敛。我们认为主机厂智能…

波斯猫 6页面 宠物动物 长毛猫 HTML5 带背景音乐 JS图片轮播特效 滚动文字 鼠标经过图片 JS时间代码

波斯猫 6页面 宠物动物 长毛猫 HTML5 带背景音乐 JS图片轮播特效 滚动文字 鼠标经过图片 JS时间代码 注册表单 宠物网页成品 海量学生网页成品 个人博客 人物明星 城市家乡 旅游景点 美食特产 购物电商 公司企业 学校大学 科普教育 宠物动物 鲜花花卉 植物水果 茶叶咖啡 健康生…

目标识别项目:基于Yolov7-LPRNet的动态车牌目标识别算法模型(一)

前言 目标识别如今以及迭代了这么多年&#xff0c;普遍受大家认可和欢迎的目标识别框架就是YOLO了。按照官方描述&#xff0c;YOLOv8 是一个 SOTA 模型&#xff0c;它建立在以前 YOLO 版本的成功基础上&#xff0c;并引入了新的功能和改进&#xff0c;以进一步提升性能和灵活性…