LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

Stream 数据流在 C# 中是如何工作的?

admin
2024年10月29日 18:54 本文热度 89

流是 C# 中的一个基本概念,用于处理可能需要一些时间才能完成的大量数据、网络通信和文件 I/O 操作。在许多情况下,这些操作的持续时间是不可预测的,因此拥有一种在等待结果时不会阻止整个过程的机制至关重要。

Stream 是一个抽象,它们携带一个字节序列。这些字节表示一些信息;一个重要的方面是,在通过 Streams 读取数据时,您不需要在内存中加载所有内容

Streams 有一些操作,可以读取一些仍然需要加载的信息。这些操作是 ReadWrite 和 Seek。那么让我们谈谈它 🧠

使用 Streams 👍 的好处

  • 非阻塞操作:Streams 允许在不冻结主线程的情况下进行数据处理,从而提高应用程序的响应能力。

  • 即时数据访问:即使操作尚未完全完成,您也可以读取或写入数据,从而实现更灵活的数据处理。

  • 资源效率:Streams 通过以块的形式处理数据而不是一次加载所有内容,帮助最大限度地减少内存使用量。

  • 可伸缩性:Streams 非常适合需要大规模数据处理的场景,例如读取日志文件或流式传输多媒体内容。

流👎的潜在缺点

  • 复杂性:处理流可能比处理静态数据更复杂,需要小心处理以避免数据损坏等问题。

  • 错误处理:流可能需要额外的错误处理,因为在流式传输期间可能会发生网络中断或文件损坏。

  • No Re-reading without Seeking:处理流后,如果不使用 Seek 方法,通常无法返回到前面的点,并非所有流都支持该方法。

可视化流 🧐

理解流的一个有用类比是将它们视为允许数据连续流动的水龙头。就像厨房水龙头一样,流量可以是慢的也可以是快的,具体取决于情况。有些流可能会很快完成,而其他流可能需要更长的时间。

在这个类比中,缓冲区的作用类似于一个桶。它会在数据流动时捕获数据,以便您访问和处理数据。如果水龙头 (流) 中断,缓冲区将保留到目前为止已收集的内容。这有助于说明数据流的概念以及缓冲区如何管理信息流。

另一个重要方面是知道当缓冲区已满时从何处恢复读取数据。如果无法记住我们在哪里停止,我们就有可能再次读取相同的数据或跳过某些部分。流的游标扮演此角色;在这个类比中,您可以将光标视为水龙头的阀门。它控制水流,允许您根据需要停止和启动溪流,确保您可以继续装满桶而不会损失一滴水。移动光标的过程称为 seek

在 C# 🔥 中使用 Stream 读取文件内容

下面是使用 C# 中的 FileStream 类从文件中读取数据的示例。_FileStream_ 类继承自抽象 Stream 类,该类提供用于处理流的方法。

using (FileStream stream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
 byte[] buffer = new byte[1024];
 int bytesRead;

 while((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Lenght)) > 0)
 {
   string content = Encoding.UTF8.GetString(buffer, 0, bytesRead);
   Console.WriteLine(content);
 }
}

在此示例中,我们使用缓冲区(一个字节数组)异步从文件中读取数据。数据根据缓冲区的容量部分流入缓冲区,_while_ 循环继续重新填充缓冲区,直到读取整个流。_Stream_ 类的 Position 属性跟踪光标在流中的最后读取位置,以便我们可以确保可以读取所有数据。

这里我们使用 Encoding.UTF8.GetString(buffer, 0, bytesRead) 将字节信息转换为字符串,但我们可以处理任何时间的信息,因为我们将其作为字节数组。

最后,我们将在控制台上打印每次执行 while 循环的字符串内容。因此,即使文件尚未读取,我们也会将内容打印到屏幕中。

处理流位置和冲洗 👀

如果需要重置流的位置,可以检查 CanSeek 是否_为 true_。如果是这样,您可以使用 Seek 倒回开头:

if (stream.CanSeek)  
{  
 stream.Seek(0, SeekOrigin.Begin);  
}

使用可写流时,请使用 Flush 确保所有缓冲数据都写入底层存储或传输到目标。这对于避免数据丢失至关重要:

using (FileStream stream = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write))
{
   byte[] dataBytes = Encoding.UTF8.GetBytes(data);

   stream.Write(dataBytes, 0, dataBytes.Length);

   stream.Flush(); // Ensure all data is written to disk or transmitted
}

流生命周期 ⏱

流的生命周期包括几个关键阶段:创建、使用(读取、写入、查找)和处置。正确了解和管理每个阶段对于高效且无差错的流操作至关重要。

  1. 创建:打开数据源(例如文件、内存或网络连接)时,将实例化流。例如,a 打开文件进行读取或写入,而 a 使用内存作为其数据源。实例化期间的配置参数(如文件路径、访问模式和缓冲区大小)设置流的行为和性能特征。FileStreamMemoryStream

  2. 使用情况:在使用阶段,数据使用读取、写入和有时查找操作流经流。这些操作与底层数据源交互,以块的形式处理数据,而不是一次处理所有数据,这对于大型数据集或实时处理特别有用。每个操作都可能影响流的位置,由内部游标跟踪,并且需要仔细管理以避免错误,例如读取超过流的末尾或在错误的位置写入。

  3. 刷新:对于可写流,尤其是涉及缓冲的流,请务必确保在流关闭之前将缓冲区中的所有数据推送到底层数据源。这是使用该方法完成的,该方法将任何剩余的缓冲数据写入其最终目标,从而防止数据丢失。Flush

  4. Disposal:正确处理流对于释放系统资源(如文件句柄、网络连接或内存缓冲区)至关重要。流实现接口,这意味着它们可以而且应该使用方法或更常见的语句来处理。Disposal 可确保正确关闭和清理所有打开的资源,从而防止可能影响系统稳定性和性能的内存泄漏或文件锁定。IDisposableDisposeusing

  5. 错误处理和完成:流在其生命周期中可能会遇到各种错误,例如文件访问问题、网络超时或数据损坏。在流操作周围使用 try-catch 块实现可靠的错误处理可确保您的应用程序能够正常处理这些情况。如果发生错误,正确处理流可确保资源不会悬空,即使在故障情况下也是如此。

管理流生命周期的最佳实践:

  • 使用流时始终使用语句。一旦退出代码块,它就会自动处理流,即使在出现异常的情况下也是如此。using

using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read))   
{      
 // Perform read operations }  
 // Stream is automatically disposed here  
}
  • 写入时定期调用,以确保传输或保存所有缓冲数据,尤其是在处理流之前。Flush

  • 在执行操作之前检查 、 和 等属性,以确保流支持所需的操作。CanReadCanWriteCanSeek

  • 在处理大量数据或执行可能阻塞的操作(例如,从慢速网络连接读取)时,请使用异步方法 (, )。ReadAsyncWriteAsync

using (FileStream stream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
       {
           // Check if the stream supports reading
           if (stream.CanRead)
           {
               byte[] buffer = new byte[1024]; // Buffer to hold read bytes
               int bytesRead;

               // Read the data from the stream asynchronously
               while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0)
               {
                   // Convert bytes to string and display
                   string content = System.Text.Encoding.UTF8.GetString(buffer, 0, bytesRead);
                   Console.WriteLine(content);
               }
           }
           else
           {
               Console.WriteLine("The stream does not support reading.");
           }
       } // The stream is automatically closed and disposed of here
  • 实施错误处理以管理异常,确保在读取或写入操作期间发生错误时正确关闭流。IOException

通过仔细管理流生命周期并遵循这些最佳实践,您可以确保您的应用程序高效处理数据、最大限度地减少资源使用并保持系统稳定性。

C# 🧬 中不同类型的流

虽然此示例使用 _FileStream_,但 C# 提供了各种流实现,包括:

  • 内存流: 将数据存储在内存中,对于临时存储和不需要磁盘写入的操作非常有用。

  • _NetworkStream_:允许通过网络传输数据,通常用于 TCP/IP 连接。

  • _CryptoStream_:应用加密转换以实现安全的数据处理,对加密和解密非常有用。

  • _BufferedStream_:为另一个流添加缓冲,增强重复读/写操作的性能。

  • _GZipStream_:使用 GZip 算法压缩或解压缩数据,非常适合减少存储空间和传输时间。

每种流类型都有独特的特性,使其适用于 C# 应用程序中的不同场景。选择流时,请考虑数据源、性能要求以及是否需要查找等因素。

流是 C# 中一种基本的通用工具,可为大规模 I/O 操作(如文件处理、网络通信和实时数据处理)实现高效的数据处理。通过掌握流使用的复杂性,包括性能优化、有效的错误处理和适当的生命周期管理,开发人员可以最大限度地利用流的优势来构建响应迅速、资源高效且可扩展的应用程序。


该文章在 2024/10/30 15:09:51 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2024 ClickSun All Rights Reserved