c# stream

1


        /// <summary>
        /// 从流获取指定长度的字节数组
        /// </summary>
        public static IEnumerable<byte[]> GetBytes(this Stream stream, long length, int size = 1024)
        {
            byte[] buffer = new byte[size];
            int len, read;

            long sum = 0;
            do
            {
                long unread = length - sum;
                read = unread >= size ? size : (int)unread;

                len = stream.Read(buffer, 0, read);
                sum += len;

                if (buffer.Length == len)
                {
                    yield return buffer;
                }
                else
                {
                    yield return buffer.Take(len).ToArray();
                }
            } while (sum < length && len > 0);
        }


### C# 中的 Stream 概念及使用方法 #### 1. 基本概念 `Stream` 是 C# 中抽象基类,表示一系列字节的数据流。它是所有具体流类型的基础,提供了一系列通用的方法和属性来操作数据流[^3]。 - `Stream` 及其派生类实现了对数据的读取 (`Read`) 和写入 (`Write`) 方法,允许开发者在字节级别上处理数据。 - 字节序列是指由多个字节组成的连续数据块,它可以代表文件、网络数据包或内存中的二进制数据等内容。 --- #### 2. 主要特性 ##### 属性说明: - **CanRead**:指示当前流是否支持读取操作。 - **CanWrite**:指示当前流是否支持写入操作。 - **CanSeek**:指示当前流是否支持定位(即能否移动指针位置)。 - **Position**:获取或设置当前流的位置。 - **Length**:返回流的总长度(以字节为单位)。 ##### 方法说明: - **Read(byte[] buffer, int offset, int count)**:从流中读取指定数量的字节到缓冲区中。 - **Write(byte[] buffer, int offset, int count)**:将缓冲区中的字节写入流中。 - **Flush()**:清除所有的缓冲区并将任何未写入的数据刷新到底层存储设备。 - **Seek(long offset, SeekOrigin origin)**:更改流中的当前位置。 - **SetLength(long value)**:设置流的长度。 --- #### 3. 使用场景与常见派生类 C# 的 `Stream` 类本身是一个抽象类,不能直接实例化。实际开发中会使用它的派生类来满足不同的需求: | 派生类 | 描述 | |--------------|----------------------------------------------------------------------| | `FileStream` | 用于文件操作,可以从磁盘文件中读取或向其中写入数据[^2]。 | | `MemoryStream` | 表示存在于内存中的字节流,适用于临时数据缓存或快速访问[^5]。 | | `NetworkStream` | 处理基于套接字的网络连接上的数据传输。 | | `CryptoStream` | 结合加密/解密功能,常用于安全通信协议实现。 | --- #### 4. 示例代码 以下是一些常见的 `Stream` 使用案例: ##### 示例 1:使用 `FileStream` 读取文件内容 ```csharp using System; using System.IO; class Program { static void Main() { string filePath = @"example.txt"; try { using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read)) { byte[] buffer = new byte[1024]; int bytesRead; while ((bytesRead = fs.Read(buffer, 0, buffer.Length)) > 0) { Console.WriteLine(System.Text.Encoding.UTF8.GetString(buffer, 0, bytesRead)); } } } catch (Exception ex) { Console.WriteLine($"Error: {ex.Message}"); } } } ``` ##### 示例 2:使用 `StreamWriter` 和 `StreamReader` 简化文本文件操作 ```csharp using System; using System.IO; class Program { static void Main() { string filePath = @"output.txt"; // 写入文件 using (StreamWriter sw = new StreamWriter(filePath)) { sw.WriteLine("Hello, world!"); } // 读取文件 using (StreamReader sr = new StreamReader(filePath)) { Console.WriteLine(sr.ReadToEnd()); } } } ``` ##### 示例 3:使用 `MemoryStream` 存储临时数据 ```csharp using System; using System.IO; class Program { static void Main() { using (MemoryStream ms = new MemoryStream()) { byte[] data = System.Text.Encoding.UTF8.GetBytes("This is a test."); ms.Write(data, 0, data.Length); ms.Position = 0; // 将指针移回起始位置 byte[] readData = new byte[data.Length]; ms.Read(readData, 0, readData.Length); Console.WriteLine(System.Text.Encoding.UTF8.GetString(readData)); } } } ``` --- #### 5. 异步操作 为了提高程序性能,尤其是当涉及大量 I/O 操作时,推荐使用异步 API 来避免阻塞主线程。例如,可以通过 `ReadAsync` 替代同步的 `Read` 方法[^4]。 ##### 示例 4:异步读取文件 ```csharp using System; using System.IO; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { string filePath = @"example.txt"; try { using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read)) { byte[] buffer = new byte[1024]; int bytesRead = await fs.ReadAsync(buffer, 0, buffer.Length); Console.WriteLine(System.Text.Encoding.UTF8.GetString(buffer, 0, bytesRead)); } } catch (Exception ex) { Console.WriteLine($"Error: {ex.Message}"); } } } ``` --- ### 总结 `Stream` 是 C# 中非常核心的一个类,它统一了各种不同类型的数据源之间的交互接口。无论是文件、网络还是内存,都可以通过继承自 `Stream` 的特定子类轻松实现高效的读写操作。同时,结合异步编程模型可以进一步优化资源利用率和用户体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值