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

news2024/12/21 19:10:58

【.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());    //方法返回解密后的字符串
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

BUUCTF---[极客大挑战 2019]Http1

1.题目描述&#xff0c;在地址框输入下面的网址 2.来到页面&#xff0c;ctrlu查看源码&#xff0c;仔细观察会看到一个.php的跳转页面 3.点进去页面提示It doesnt come from https://Sycsecret.buuoj.cn 4.页面提示它不是来源于这个网址&#xff0c;我们需要用bp抓包对数据进行…

matlab 写入格式化文本文件

目录 一、save函数 二、fprintf函数 matlab 写入文本文件可以使用save和fprintf函数 save输出结果: fprintf输出结果: 1.23, 2.34, 3.45 4.56, 5.67, 6.78 7.89, 8.90, 9.01 可以看出fprintf输出结果更加人性化,符合要求,下面分别介绍。 一、save函数 …

深入了解 JavaScript 混淆加密和环境检测

JavaScript混淆加密是一种通过修改代码结构和命名约定来增加代码的复杂性&#xff0c;使其难以被理解和逆向工程的技术。在这篇文章中&#xff0c;我们将深入探讨JS混淆加密的一些逻辑&#xff0c;并介绍如何通过环境检测来提高代码的安全性。我们将使用案例代码演示这些概念。…

外汇110:社交媒体上的金融欺诈激增,网民该如何识别骗局?

社交媒体平台上的金融欺诈正在以令人担忧的速度增加。从某种程度上来说&#xff0c;社交媒体已成为诈骗者的门户&#xff0c;因为它使欺诈者能够方便地与用户联系&#xff0c;并创建一个隐藏在虚假社交媒体资料后面、充斥着非法投资内容的在线角色。 由于社交媒体在我们日常生活…

智慧城市中的公共服务创新:让城市生活更便捷

目录 一、引言 二、智慧城市公共服务创新的实践 1、智慧交通系统 2、智慧医疗服务 3、智慧教育系统 4、智慧能源管理 三、智慧城市公共服务创新的挑战 四、智慧城市公共服务创新的前景 五、结论 一、引言 随着信息技术的迅猛发展&#xff0c;智慧城市已成为现代城市发…

基于React低代码平台开发:构建高效、灵活的应用新范式

文章目录 一、React与低代码平台的结合优势二、基于React的低代码平台开发挑战三、基于React的低代码平台开发实践四、未来展望《低代码平台开发实践&#xff1a;基于React》编辑推荐内容简介作者简介目录前言为什么要写这本书 读者对象如何阅读本书 随着数字化转型的深入&…

用BIO实现tomcat

一、前言 本课程的难度较高&#xff0c;需要将Servlet原理和IO课程全部学完。 二、当前项目使用方式 (1).自定义servlet 自定义servlet需要实现WebServlet并且实现name和urlMapping 重启进行访问 http://localhost:8090/myServlet (2).自定义html 重启进行访问 http://loc…

四川古力未来科技抖音小店:未来零售的新风口

随着互联网的快速发展&#xff0c;电商行业日新月异&#xff0c;短视频平台抖音凭借其庞大的用户群体和独特的内容形式&#xff0c;已经成为当下最热门的社交媒体之一。抖音小店作为抖音平台上的一个重要功能&#xff0c;正逐渐展现出其巨大的商业潜力和发展前景。本文将探讨抖…

【脑科学相关合集】有关脑影像数据相关介绍的笔记及有关脑网络的笔记合集

【脑科学相关合集】有关脑影像数据相关介绍的笔记及有关脑网络的笔记合集 前言脑模板方面相关笔记清单 基于脑网络的方法方面数据基本方面 前言 这里&#xff0c;我将展开有关我自己关于脑影像数据相关介绍的笔记及有关脑网络的笔记合集。其中&#xff0c;脑网络的相关论文主要…

C++原子变量的使用案例

说明 核心原子变量是pDeviceStatus&#xff0c;该变量的夸线程修改&#xff0c;就不需要使用锁了&#xff1b; std::atomic<IPDeviceStatus*> pDeviceStatus new IPDeviceStatus(); 代码功能 某公共场所使用的IP喇叭&#xff0c;类似物联网设备&#xff0c;基于嵌入…

Vue3自定义文章列表组件

一、Vue3的代码展示 <template><div><div v-for"article in articles" :key"article.id" class"article-card"><div class"author-info"><img :src"article.avatar" alt"Author Avatar&qu…

水电站数字孪生:水力发电在可视化领域的应用

自水轮机的早期发明被用于农业灌溉&#xff0c;到 18 世纪末期的工业革命促使水轮机技术的改良&#xff0c;再到 19 世纪末水利发电的崛起&#xff0c;直至今日&#xff0c;智慧水电站数字孪生技术正处于蓬勃发展之中。通过整合物联网、大数据、云计算等现代信息技术&#xff0…

PYCHARM PYSIDE6 QT 打包异常3种处理方式 no qt platform plugin could be initialized

安装有PYSIDE6的电脑 异常错误 … no qt platform plugin could be initialized … 变量名&#xff1a;QT_QPA_PLATFORM_PLUGIN_PATH &#xff08;一个字都不能改&#xff01;&#xff01;&#xff09; 自己环境变量值&#xff1a;D:\Users\topma\anaconda3\Lib\site-package…

【STM32】STM32学习笔记-FLASH闪存(48)

00. 目录 文章目录 00. 目录01. FLASH简介02. 闪存模块组织03. FLASH基本结构04. FLASH解锁05. 使用指针访问存储器06. 程序存储器编程07. 选项字节08. 选项字节编程09. 选项字节擦除10. 器件电子签名11. 附录 01. FLASH简介 STM32F1系列的FLASH包含程序存储器、系统存储器和选…

HarmonyOS Stage模型 用程序运行切换 验证UIAbility 启动模式(下) 验证:specified启动模式 Ability间切换

上文 HarmonyOS Stage模型 用程序运行切换 验证UIAbility 启动模式(上) 验证:singleton、multiton、standard启动模式 我们已经验证完了 singleton multiton standard 三种启动模式 留下了毕竟复杂的 specified 这里 首先 我们要写两个不同的界面 index 编写代码如下 import…

就业班 2401--2.29 Linux Day8--存储管理2(LVM)+swap+磁盘阵列raid

&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;小伙伴们一定要看到最后&#xff0c;有彩蛋呢^--^ 一、存储管理Ⅱ 逻辑卷LVM &#xff08;Logical Volume Manager&#xff08;逻辑卷管理&#xff09;的简写&#xff09; LVM管理 lvm概念&#xf…

即时设计案例分享: 网页设计案例解析

优秀的网页设计案例可以帮助设计快速完成设计项目&#xff0c;优秀的网页设计网站也是设计师的灵感电站。网页承载着品牌希望向访问者传递的信息。当用户进入网站时&#xff0c;人们对网站的第一印象开始潜移默化地形成。因此&#xff0c;优秀的网页设计非常重要&#xff0c;这…

uniapp问卷调查(单选)

前言 该代码片段只支持问卷调查的单选功能 使用组件库 配置 | uView 2.0 - 全面兼容 nvue 的 uni-app 生态框架 - uni-app UI 框架 (uviewui.com) 代码 <template> <view> <view v-for"(item, index) in radiolist1" :key"index"> …

LeetCode --- 无重复字符的最长子串

题目描述 无重复字符的最长子串 找到无重复的最长连续字符串。 示例1中 abc | bca | cab 都符合题意。输出3即可。 代码 可以使用暴力枚举 哈希表&#xff0c;哈希表来判断是否重复&#xff0c;枚举来判断每一种情况&#xff0c;需要开两层for循环&#xff0c;时间复杂度n…

Linux --- 应用层 | HTTP | HTTPS

前言 前面写的TCP/UDP客户端在访问服务端的时候&#xff0c;需要输入ip地址和端口号才可以访问&#xff0c; 但在现实中&#xff0c;我们访问一个网站是直接输入的一个域名&#xff0c;而不是使用的ip地址端口号。 比如在访问百度 https://www.baidu.com/的时候&#xff0c; …