C# FileStream分块读取异常:仅currentChunk为0时功能正常
修复Stream分页读取方法的问题
你的方法仅在currentChunk=0时正常工作,核心问题有两个:
- 没有将流的读取位置定位到目标chunk的起始点,导致每次都从流的当前位置开始读取
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
相关产品推荐
相关产品推荐

