.NET中读取完整Stream后如何测量其长度?
在.NET中读取未知长度Stream后获取总长度的简便方案
如果你不想用复杂的包装器,也不想把Stream内容存入内存,有两种极简方案可以实现:
方案一:读取时实时统计字节数
这是最直接的方式——在读取Stream的循环过程中,直接累加每次读取到的字节数,读取完成后这个累加值就是总长度。完全不需要额外的包装类,代码侵入性极低。
示例代码:
long totalBytes = 0; var buffer = new byte[4096]; // 缓冲区大小可根据实际场景调整,比如8192 int bytesRead; while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0) { // 在这里处理读取到的内容,比如写入文件、传递给业务逻辑 ProcessReceivedData(buffer, bytesRead); totalBytes += bytesRead; } // 读取完成后,totalBytes就是整个Stream的总长度
方案二:极简计数包装Stream
如果你的读取逻辑是封装好的(比如需要把Stream传给第三方方法处理),不想修改原有读取代码,可以写一个超轻量的包装Stream,仅负责统计读取的字节数,比CryptoStream的实现简单得多。
计数Stream实现:
public class CountingStream : Stream { private readonly Stream _innerStream; public long TotalBytesRead { get; private set; } public CountingStream(Stream innerStream) { _innerStream = innerStream ?? throw new ArgumentNullException(nameof(innerStream)); } public override int Read(byte[] buffer, int offset, int count) { int bytesRead = _innerStream.Read(buffer, offset, count); if (bytesRead > 0) TotalBytesRead += bytesRead; return bytesRead; } // 以下方法直接委托给内部Stream,无需额外逻辑 public override bool CanRead => _innerStream.CanRead; public override bool CanSeek => _innerStream.CanSeek; public override bool CanWrite => _innerStream.CanWrite; public override long Length => _innerStream.Length; public override long Position { get => _innerStream.Position; set => _innerStream.Position = value; } public override void Flush() => _innerStream.Flush(); public override long Seek(long offset, SeekOrigin origin) => _innerStream.Seek(offset, origin); public override void SetLength(long value) => _innerStream.SetLength(value); public override void Write(byte[] buffer, int offset, int count) => _innerStream.Write(buffer, offset, count); protected override void Dispose(bool disposing) { if (disposing) _innerStream.Dispose(); base.Dispose(disposing); } }
使用方式:
using var countingStream = new CountingStream(yourOriginalStream); // 调用原有读取逻辑处理countingStream YourExistingReadLogic(countingStream); // 读取完成后获取总长度 long totalLength = countingStream.TotalBytesRead;
两种方案都完全符合你的要求:不需要将Stream内容存入内存,实现简单直接,避免了复杂包装器的冗余代码。
内容的提问来源于stack exchange,提问作者Ykok
相关产品推荐
相关产品推荐

