C#中使用FileStream与MemoryStream操作字节数组详解

远山来客
远山来客
发布时间:2026-10-15| 6人浏览过
原创

在C#开发中,经常需要对文件的二进制数据进行底层操作。System.IO.Stream是所有流的抽象基类,而 FileStream 和 MemoryStream 是其最常用的实现。本文将详细解析如何使用这两个类来读取、写入和处理 byte[](字节数组),包括基础读写、分块处理、异步操作以及内存流的高级用法。

一、Stream 类概述

在 .NET Framework 中,文件是存储在磁盘上的数据集,具有路径和名称;而流(Stream)则是为数据访问提供统一接口的抽象概念。流不仅限于磁盘文件,还可以代表网络数据、内存数据等。

1. Stream 基类属性与方法

Stream 是所有流的抽象基类,核心特性如下:

  • 属性:CanRead(是否可读)、CanWrite(是否可写)、CanSeek(是否支持定位/查找)、Length(流长度)、Position(当前流位置)等。
  • 方法:Read/Write(字节序列读写)、Seek(设置查找位置)、Flush(清除缓冲区)、Close(关闭流)。

2. 常见流类型对比

  • FileStream:主要用于以流的形式对磁盘文件进行读写,支持管道、标准输入输出等操作。
  • MemoryStream:在内存中创建流,无需在硬盘上创建临时文件,适合暂时缓存数据。
  • BufferedStream:提供缓冲功能,通过减少操作系统调用次数来提高读写效率。
  • NetworkStream:为网络访问提供基础数据流。

二、文件流类 FileStream 的使用

FStream 公开了以文件为主的 Stream 功能,直接操作字节和字节数组,非常适合处理非文本的二进制文件。

第1步:完整读文件

适用于小文件。将文件内容一次性读取到字节数组中。

// 创建 d:\file.txt 的 FileStream 对象,使用 FileOpenOrCreate 模式
using (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);
    
    // 解码显示 (注意:若文件非UTF-8编码,需调整 Encoding)
    string result = Encoding.UTF8.GetString(bData);
    Console.WriteLine(result);
}

第2步:分块读取文件

对于大文件,建议分块读取以避免内存溢出或IO阻塞。

int bufferSize = 4096; // 设定合适的缓冲区大小,如 4KB
// 只读模式打开文件
using (FileStream fstream = new FileStream(@"d:\file.txt", FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize))
{
    byte[] bData = new byte[bufferSize];
    int bytesRead;
    
    // 循环读取直到返回值为 0
    while ((bytesRead = fstream.Read(bData, 0, bData.Length)) > 0)
    {
        string chunk = Encoding.UTF8.GetString(bData, 0, bytesRead);
        Console.WriteLine(chunk);
    }
}

第3步:异步读写文件

利用 BeginRead 和 EndRead 或非阻塞的 ReadAsync 提升吞吐量。这里演示基于回调的传统异步模式:

ManualResetEvent mEvent = new ManualResetEvent(false);
int bufferSize = 4096;
byte[] bData = new byte[bufferSize];

using (FileStream fstream = new FileStream(@"d:\file.txt", FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize, true))
{
    AsyncCallback callback = null;
    callback = (IAsyncResult ar) => 
    {
        int bytesRead = fstream.EndRead(ar);
        if (bytesRead > 0)
        {
            string result = Encoding.UTF8.GetString(bData, 0, bytesRead);
            Console.WriteLine(result);
            // 继续读取下一块
            fstream.BeginRead(bData, 0, bufferSize, callback, null);
        }
        else
        {
            Console.WriteLine("读取完成");
            mEvent.Set();
        }
    };

    // 发起首次异步读取
    IAsyncResult async = fstream.BeginRead(bData, 0, bufferSize, callback, null);
    // 等待异步操作完成(超时5秒)
    mEvent.WaitOne(5000, false);
}

第4步:向文件写入数据

将字符串转为字节数组后写入文件。

using (FileStream fstream = new FileStream(@"d:\write_file.txt", FileMode.Create))
{
    byte[] bData = Encoding.UTF8.GetBytes("Hello FileStream!");
    fstream.Write(bData, 0, bData.Length);
    fstream.Flush(); // 确保数据真正写入磁盘
}

三、内存流 MemoryStream 进阶应用

MemoryStream 在内存中维护一个字节数组,容量可以自动增长。常用于图像解码、数据库存储、加密传输等场景。

示例:在内存中进行读写操作

UnicodeEncoding uniEncoding = new UnicodeEncoding();
// 准备要写入的数据
byte[] firstString = uniEncoding.GetBytes("First part: ");
byte[] secondString = uniEncoding.GetBytes("Second part.");

using (MemoryStream memStream = new MemoryStream())
{
    // 写入第一个字符串
    memStream.Write(firstString, 0, firstString.Length);
    
    // 逐个字节写入第二个字符串
    foreach(byte b in secondString)
    {
        memStream.WriteByte(b);
    }

    Console.WriteLine($"Capacity={memStream.Capacity}, Length={memStream.Length}");

    // 重置指针到开头进行读取
    memStream.Position = 0;
    byte[] buffer = new byte[memStream.Length];
    memStream.Read(buffer, 0, buffer.Length);
    
    char[] chars = uniEncoding.GetChars(buffer);
    Console.WriteLine(new string(chars));
}

Toarray() 与 GetBuffer() 的核心区别

这是面试和实际应用中的高频考点:

  • ToArray():创建一个与流数据完全匹配的新字节数组副本。安全,但会产生内存分配开销(略慢)。
  • GetBuffer():返回用于构造该流的底层原始字节数组引用。速度极快且无额外内存分配,但数组的 Length 可能大于实际使用的数据量(存在空白字节)。如果修改这个缓冲区,原 MemoryStream 的数据也会随之改变,需注意生命周期管理。
相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。