You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# FileStream分块读取异常:仅currentChunk为0时功能正常

修复Stream分页读取方法的问题

你的方法仅在currentChunk=0时正常工作,核心问题有两个:

  1. 没有将流的读取位置定位到目标chunk的起始点,导致每次都从流的当前位置开始读取
  2. ReadAsync的第二个参数使用错误:该参数是缓冲区的偏移量,而非流的读取位置,传入startPosition会导致缓冲区越界(当startPosition大于缓冲区长度时)

以下是修复后的完整代码:

public async Task<byte[]> GetStreamChunkAsync(Stream inputStream, int numberOfChunks, int currentChunk)
{
    if (numberOfChunks <= 0 || currentChunk < 0 || currentChunk >= numberOfChunks)
    {
        throw new ArgumentOutOfRangeException("Invalid numberOfChunks or currentChunk values");
    }

    // 检查流是否支持查找操作(FileStream支持,NetworkStream等流可能不支持)
    if (!inputStream.CanSeek)
    {
        throw new InvalidOperationException("The input stream does not support seeking.");
    }

    long totalLength = inputStream.Length;
    int bufferSize = (int)Math.Ceiling((double)totalLength / numberOfChunks);
    
    long startPosition = (long)currentChunk * bufferSize;
    
    // 计算当前chunk实际需读取的字节数,避免超出流末尾
    int remainingBytes = (int)Math.Min(bufferSize, totalLength - startPosition);
    
    if (remainingBytes <= 0)
    {
        return Array.Empty<byte>();
    }

    byte[] buffer = new byte[remainingBytes];

    // 将流的读取指针定位到当前chunk的起始位置
    inputStream.Position = startPosition;

    // 读取数据到缓冲区的起始位置(偏移量为0)
    int bytesRead = await inputStream.ReadAsync(buffer, 0, remainingBytes);

    // 处理实际读取字节数小于预期的情况(如流被截断)
    if (bytesRead < remainingBytes)
    {
        Array.Resize(ref buffer, bytesRead);
    }

    return buffer;
}

关键修复说明:

  • 流位置定位:通过inputStream.Position = startPosition将读取指针移到当前chunk的起始处,确保从正确位置开始读取
  • 修正ReadAsync参数:第二个参数改为0,将读取的字节写入缓冲区的起始位置,避免缓冲区越界
  • 添加CanSeek检查:避免在不支持定位的流上调用Position属性抛出异常
  • 溢出防护:用long类型存储流总长度和起始位置,避免流长度超过int最大值时出现数值溢出
  • 边界处理:当剩余字节数为0时返回空数组,同时处理实际读取字节数小于预期的情况

内容的提问来源于stack exchange,提问作者Regestea

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 21:00:05